From e5fe93178349d24b7c9a3a7a9645b6c80d1bae11 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 8 Aug 2023 11:30:22 +0200 Subject: [PATCH 001/221] voice - have a `VSFloat32Array` primitive that is serializable --- src/vs/base/common/buffer.ts | 32 ++++++++++++++++++++++++++ src/vs/base/common/marshalling.ts | 3 ++- src/vs/base/common/marshallingIds.ts | 3 ++- src/vs/base/test/common/buffer.test.ts | 21 ++++++++++++++++- 4 files changed, 56 insertions(+), 3 deletions(-) diff --git a/src/vs/base/common/buffer.ts b/src/vs/base/common/buffer.ts index 08736ab8c0b..1981217fd1c 100644 --- a/src/vs/base/common/buffer.ts +++ b/src/vs/base/common/buffer.ts @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { Lazy } from 'vs/base/common/lazy'; +import { MarshalledId } from 'vs/base/common/marshallingIds'; import * as streams from 'vs/base/common/stream'; declare const Buffer: any; @@ -439,3 +440,34 @@ export function encodeBase64({ buffer }: VSBuffer, padded = true, urlSafe = fals return output; } + +export interface VSFloat32ArrayComponents { + readonly $mid: MarshalledId.Float32Array; + readonly values: number[]; +} + +export class VSFloat32Array { + + readonly buffer: Float32Array; + readonly byteLength: number; + + static wrap(actual: Float32Array): VSFloat32Array { + return new VSFloat32Array(actual); + } + + private constructor(buffer: Float32Array) { + this.buffer = buffer; + this.byteLength = this.buffer.byteLength; + } + + toJSON(): VSFloat32ArrayComponents { + return { + $mid: MarshalledId.Float32Array, + values: Array.from(this.buffer.map(value => value)) + }; + } + + static revive(raw: VSFloat32ArrayComponents): VSFloat32Array { + return VSFloat32Array.wrap(new Float32Array(raw.values)); + } +} diff --git a/src/vs/base/common/marshalling.ts b/src/vs/base/common/marshalling.ts index 67a29703cdc..087ad5d0f58 100644 --- a/src/vs/base/common/marshalling.ts +++ b/src/vs/base/common/marshalling.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { VSBuffer } from 'vs/base/common/buffer'; +import { VSBuffer, VSFloat32Array } from 'vs/base/common/buffer'; import { regExpFlags } from 'vs/base/common/strings'; import { URI, UriComponents } from 'vs/base/common/uri'; import { MarshalledId } from './marshallingIds'; @@ -54,6 +54,7 @@ export function revive(obj: any, depth = 0): Revived { case MarshalledId.Uri: return URI.revive(obj); case MarshalledId.Regexp: return new RegExp(obj.source, obj.flags); case MarshalledId.Date: return new Date(obj.source); + case MarshalledId.Float32Array: return VSFloat32Array.revive(obj); } if ( diff --git a/src/vs/base/common/marshallingIds.ts b/src/vs/base/common/marshallingIds.ts index abd7698ed92..7cb27d18f36 100644 --- a/src/vs/base/common/marshallingIds.ts +++ b/src/vs/base/common/marshallingIds.ts @@ -20,5 +20,6 @@ export const enum MarshalledId { NotebookCellActionContext, NotebookActionContext, TestItemContext, - Date + Date, + Float32Array } diff --git a/src/vs/base/test/common/buffer.test.ts b/src/vs/base/test/common/buffer.test.ts index 5a37943b658..969a96d9303 100644 --- a/src/vs/base/test/common/buffer.test.ts +++ b/src/vs/base/test/common/buffer.test.ts @@ -5,7 +5,8 @@ import * as assert from 'assert'; import { timeout } from 'vs/base/common/async'; -import { bufferedStreamToBuffer, bufferToReadable, bufferToStream, decodeBase64, encodeBase64, newWriteableBufferStream, readableToBuffer, streamToBuffer, VSBuffer } from 'vs/base/common/buffer'; +import { bufferedStreamToBuffer, bufferToReadable, bufferToStream, decodeBase64, encodeBase64, newWriteableBufferStream, readableToBuffer, streamToBuffer, VSBuffer, VSFloat32Array } from 'vs/base/common/buffer'; +import { parse, stringify } from 'vs/base/common/marshalling'; import { peekStream } from 'vs/base/common/stream'; suite('Buffer', () => { @@ -477,4 +478,22 @@ suite('Buffer', () => { assert.throws(() => decodeBase64('invalid!')); }); }); + + suite('Float32Array', () => { + + test('serialization', () => { + const array = new Float32Array(10); + for (let i = 0; i < array.length; i++) { + array[i] = i === 0 ? 0 : Math.random(); + } + + const buffer = VSFloat32Array.wrap(array); + const serialized = stringify(buffer); + const deserialized = parse(serialized); + + assert.ok(deserialized instanceof VSFloat32Array); + assert.deepStrictEqual(array, deserialized.buffer); + assert.deepStrictEqual(array.byteLength, deserialized.byteLength); + }); + }); }); From 707bffbdae207740940e86a11b8178978515f9d0 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 8 Aug 2023 17:08:44 +0200 Subject: [PATCH 002/221] voice - scaffold a basic voice recorder service --- build/lib/i18n.resources.json | 4 + src/vs/code/electron-main/app.ts | 16 +- .../node/sharedProcess/sharedProcessMain.ts | 9 ++ .../common/voiceRecognitionService.ts | 31 ++++ .../node/voiceRecognitionService.ts | 38 +++++ .../electron-sandbox/chat.contribution.ts | 50 +++++++ .../voiceRecognitionService.ts | 9 ++ .../workbenchVoiceRecognitionService.ts | 140 ++++++++++++++++++ src/vs/workbench/workbench.desktop.main.ts | 5 + 9 files changed, 300 insertions(+), 2 deletions(-) create mode 100644 src/vs/platform/voiceRecognition/common/voiceRecognitionService.ts create mode 100644 src/vs/platform/voiceRecognition/node/voiceRecognitionService.ts create mode 100644 src/vs/workbench/contrib/chat/electron-sandbox/chat.contribution.ts create mode 100644 src/vs/workbench/services/voiceRecognition/electron-sandbox/voiceRecognitionService.ts create mode 100644 src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts diff --git a/build/lib/i18n.resources.json b/build/lib/i18n.resources.json index f83225cc974..15a06c1a021 100644 --- a/build/lib/i18n.resources.json +++ b/build/lib/i18n.resources.json @@ -78,6 +78,10 @@ "name": "vs/workbench/services/assignment", "project": "vscode-workbench" }, + { + "name": "vs/workbench/services/voiceRecognition", + "project": "vscode-workbench" + }, { "name": "vs/workbench/contrib/extensions", "project": "vscode-workbench" diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index bd6fb95a75d..9c79498b8f5 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -162,24 +162,36 @@ export class CodeApplication extends Disposable { const isUrlFromWebview = (requestingUrl: string | undefined) => requestingUrl?.startsWith(`${Schemas.vscodeWebview}://`); + const allowedPermissionsInMainFrame = new Set([ + 'media' + ]); + const allowedPermissionsInWebview = new Set([ 'clipboard-read', 'clipboard-sanitized-write', ]); - session.defaultSession.setPermissionRequestHandler((_webContents, permission /* 'media' | 'geolocation' | 'notifications' | 'midiSysex' | 'pointerLock' | 'fullscreen' | 'openExternal' */, callback, details) => { + session.defaultSession.setPermissionRequestHandler((_webContents, permission, callback, details) => { if (isUrlFromWebview(details.requestingUrl)) { return callback(allowedPermissionsInWebview.has(permission)); } + if (details.isMainFrame && details.securityOrigin === 'vscode-file://vscode-app/') { + return callback(allowedPermissionsInMainFrame.has(permission)); + } + return callback(false); }); - session.defaultSession.setPermissionCheckHandler((_webContents, permission /* 'media' */, _origin, details) => { + session.defaultSession.setPermissionCheckHandler((_webContents, permission, _origin, details) => { if (isUrlFromWebview(details.requestingUrl)) { return allowedPermissionsInWebview.has(permission); } + if (details.isMainFrame && details.securityOrigin === 'vscode-file://vscode-app/') { + return allowedPermissionsInMainFrame.has(permission); + } + return false; }); diff --git a/src/vs/code/node/sharedProcess/sharedProcessMain.ts b/src/vs/code/node/sharedProcess/sharedProcessMain.ts index f911b0da431..7092cc2b8ec 100644 --- a/src/vs/code/node/sharedProcess/sharedProcessMain.ts +++ b/src/vs/code/node/sharedProcess/sharedProcessMain.ts @@ -112,6 +112,8 @@ import { IRemoteSocketFactoryService, RemoteSocketFactoryService } from 'vs/plat import { RemoteConnectionType } from 'vs/platform/remote/common/remoteAuthorityResolver'; import { nodeSocketFactory } from 'vs/platform/remote/node/nodeSocketFactory'; import { NativeEnvironmentService } from 'vs/platform/environment/node/environmentService'; +import { IVoiceRecognitionService } from 'vs/platform/voiceRecognition/common/voiceRecognitionService'; +import { VoiceRecognitionService } from 'vs/platform/voiceRecognition/node/voiceRecognitionService'; class SharedProcessMain extends Disposable { @@ -351,6 +353,9 @@ class SharedProcessMain extends Disposable { // Remote Tunnel services.set(IRemoteTunnelService, new SyncDescriptor(RemoteTunnelService)); + // Voice Recognition + services.set(IVoiceRecognitionService, new SyncDescriptor(VoiceRecognitionService, undefined, false /* proxied to other processes */)); + return new InstantiationService(services); } @@ -408,6 +413,10 @@ class SharedProcessMain extends Disposable { // Remote Tunnel const remoteTunnelChannel = ProxyChannel.fromService(accessor.get(IRemoteTunnelService)); this.server.registerChannel('remoteTunnel', remoteTunnelChannel); + + // Voice Recognition + const voiceRecognitionChannel = ProxyChannel.fromService(accessor.get(IVoiceRecognitionService)); + this.server.registerChannel('voiceRecognition', voiceRecognitionChannel); } private registerErrorHandler(logService: ILogService): void { diff --git a/src/vs/platform/voiceRecognition/common/voiceRecognitionService.ts b/src/vs/platform/voiceRecognition/common/voiceRecognitionService.ts new file mode 100644 index 00000000000..0cc3310df97 --- /dev/null +++ b/src/vs/platform/voiceRecognition/common/voiceRecognitionService.ts @@ -0,0 +1,31 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { VSFloat32Array } from 'vs/base/common/buffer'; +import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; + +export const IVoiceRecognitionService = createDecorator('voiceRecognitionService'); + +export interface IAudioBuffer { + readonly sampleRate: 16000; + readonly channelCount: 1; + readonly length: number; + readonly channelData: VSFloat32Array; +} + +export interface IVoiceRecognitionService { + + readonly _serviceBrand: undefined; + + /** + * Given a buffer of audio data, attempts to + * transcribe the spoken words into text. + * + * @param buffer the audio data obtained from + * the microphone as PCM 32-bit float mono in + * 16khz. + */ + transcribe(buffer: IAudioBuffer): Promise; +} diff --git a/src/vs/platform/voiceRecognition/node/voiceRecognitionService.ts b/src/vs/platform/voiceRecognition/node/voiceRecognitionService.ts new file mode 100644 index 00000000000..cb57192e299 --- /dev/null +++ b/src/vs/platform/voiceRecognition/node/voiceRecognitionService.ts @@ -0,0 +1,38 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { ILogService } from 'vs/platform/log/common/log'; +import { IAudioBuffer, IVoiceRecognitionService } from 'vs/platform/voiceRecognition/common/voiceRecognitionService'; + +export class VoiceRecognitionService implements IVoiceRecognitionService { + + declare readonly _serviceBrand: undefined; + + constructor( + @ILogService private readonly logService: ILogService + ) { } + + async transcribe(buffer: IAudioBuffer): Promise { + this.logService.info(`[voice] transcribe(${buffer.length}): Begin`); + + const modulePath = process.env.VSCODE_VOICE_MODULE_PATH; + if (!modulePath) { + throw new Error('Voice recognition not yet supported!'); + } + + const voiceModule: { transcribe: (audioBuffer: { channelCount: 1; length: number; sampleRate: 16000; channelData: Float32Array }) => Promise } = require.__$__nodeRequire(modulePath); + + const text = await voiceModule.transcribe({ + channelCount: buffer.channelCount, + length: buffer.length, + sampleRate: buffer.sampleRate, + channelData: buffer.channelData.buffer + }); + + this.logService.info(`[voice] transcribe(${buffer.length}): End (text: "${text}"))`); + + return text; + } +} diff --git a/src/vs/workbench/contrib/chat/electron-sandbox/chat.contribution.ts b/src/vs/workbench/contrib/chat/electron-sandbox/chat.contribution.ts new file mode 100644 index 00000000000..0f0c9474e27 --- /dev/null +++ b/src/vs/workbench/contrib/chat/electron-sandbox/chat.contribution.ts @@ -0,0 +1,50 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { toAction } from 'vs/base/common/actions'; +import { CancellationTokenSource } from 'vs/base/common/cancellation'; +import { DisposableStore, toDisposable } from 'vs/base/common/lifecycle'; +import { CommandsRegistry } from 'vs/platform/commands/common/commands'; +import { INotificationService, NotificationPriority, Severity } from 'vs/platform/notification/common/notification'; +import { IWorkbenchVoiceRecognitionService } from 'vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService'; + +let activeVoiceTranscription: DisposableStore | undefined; + +function stopVoiceTranscription() { + activeVoiceTranscription?.dispose(); + activeVoiceTranscription = undefined; +} + +CommandsRegistry.registerCommand('workbench.action.toggleVoiceTranscription', async services => { + if (activeVoiceTranscription) { + stopVoiceTranscription(); + } else { + const voiceRecognitionService = services.get(IWorkbenchVoiceRecognitionService); + const notificationService = services.get(INotificationService); + + activeVoiceTranscription = new DisposableStore(); + + const cts = new CancellationTokenSource(); + activeVoiceTranscription.add(toDisposable(() => cts.dispose(true))); + + const voiceTranscriptionNotification = notificationService.notify({ + severity: Severity.Info, + priority: NotificationPriority.URGENT, + sticky: true, + message: 'Listening...', + actions: { + primary: [ + toAction({ id: 'stopVoiceTranscription', label: 'Stop', run: () => stopVoiceTranscription() }) + ] + } + }); + + activeVoiceTranscription.add(toDisposable(() => voiceTranscriptionNotification.close())); + + activeVoiceTranscription.add(voiceRecognitionService.transcribe(cts.token)(text => { + voiceTranscriptionNotification.updateMessage(text); + })); + } +}); diff --git a/src/vs/workbench/services/voiceRecognition/electron-sandbox/voiceRecognitionService.ts b/src/vs/workbench/services/voiceRecognition/electron-sandbox/voiceRecognitionService.ts new file mode 100644 index 00000000000..e8b4e771ffa --- /dev/null +++ b/src/vs/workbench/services/voiceRecognition/electron-sandbox/voiceRecognitionService.ts @@ -0,0 +1,9 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { registerSharedProcessRemoteService } from 'vs/platform/ipc/electron-sandbox/services'; +import { IVoiceRecognitionService } from 'vs/platform/voiceRecognition/common/voiceRecognitionService'; + +registerSharedProcessRemoteService(IVoiceRecognitionService, 'voiceRecognition'); diff --git a/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts b/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts new file mode 100644 index 00000000000..a98131381ce --- /dev/null +++ b/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts @@ -0,0 +1,140 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { localize } from 'vs/nls'; +import { VSFloat32Array } from 'vs/base/common/buffer'; +import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation'; +import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions'; +import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; +import { IVoiceRecognitionService } from 'vs/platform/voiceRecognition/common/voiceRecognitionService'; +import { Emitter, Event } from 'vs/base/common/event'; +import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/progress'; +import { DeferredPromise } from 'vs/base/common/async'; + +export const IWorkbenchVoiceRecognitionService = createDecorator('workbenchVoiceRecognitionService'); + +export interface IWorkbenchVoiceRecognitionService { + + readonly _serviceBrand: undefined; + + /** + * Starts listening to the microphone transcribing the voice to text. + * + * @param cancellation a cancellation token to stop transcribing and + * listening to the microphone. + */ + transcribe(cancellation: CancellationToken): Event; +} + +// TODO@voice +// - load `navigator.mediaDevices.getUserMedia` lazily on startup? or would it trigger a permission prompt? +// - figure out the ugly `any` cast for AudioContext +// - how to prevent data processing accumulation when processing is slow? +// - how to make this a singleton service that enables ref-counting on multiple callers? +// - cancellation should flow to the shared process +// - voice module should directly transcribe the PCM32 data +// - we should transfer the Float32Array directly without serialisation overhead + +export class WorkbenchVoiceRecognitionService implements IWorkbenchVoiceRecognitionService { + + declare readonly _serviceBrand: undefined; + + private static readonly AUDIO_TIME_SLICE = 2000; + private static readonly AUDIO_MIME_TYPE = 'audio/webm;codecs=opus'; + + constructor( + @IVoiceRecognitionService private readonly voiceRecognitionService: IVoiceRecognitionService, + @IProgressService private readonly progressService: IProgressService + ) { } + + transcribe(cancellation: CancellationToken): Event { + const cts = new CancellationTokenSource(cancellation); + const emitter = new Emitter(); + cancellation.onCancellationRequested(() => emitter.dispose()); + + this.doTranscribe(emitter, cts.token); + + return emitter.event; + } + + private async doTranscribe(emitter: Emitter, token: CancellationToken): Promise { + return this.progressService.withProgress({ + location: ProgressLocation.Window, + title: localize('voiceTranscription', "Voice Transcription"), + }, async progress => { + const recordingDone = new DeferredPromise(); + + progress.report({ message: localize('voiceTranscriptionGettingReady', "Getting microphone ready...") }); + + const audioDevice = await navigator.mediaDevices.getUserMedia({ audio: true }); + + if (token.isCancellationRequested) { + return; + } + + const audioRecorder = new MediaRecorder(audioDevice, { mimeType: WorkbenchVoiceRecognitionService.AUDIO_MIME_TYPE }); + audioRecorder.start(WorkbenchVoiceRecognitionService.AUDIO_TIME_SLICE); + + token.onCancellationRequested(() => { + audioRecorder.stop(); + recordingDone.complete(); + }); + + progress.report({ message: localize('voiceTranscriptionRecording', "Recording from microphone...") }); + + const chunks: Blob[] = []; + audioRecorder.ondataavailable = e => { + chunks.push(e.data); + + this.doTranscribeChunk(chunks, emitter, token); + }; + + return recordingDone.p; + }); + } + + private async doTranscribeChunk(chunks: Blob[], emitter: Emitter, token: CancellationToken): Promise { + if (token.isCancellationRequested) { + return; + } + + const blob = new Blob(chunks); + const blobBuffer = await blob.arrayBuffer(); + if (token.isCancellationRequested) { + return; + } + + const audioContextOptions = { + sampleRate: 16000 as const, + channelCount: 1 as const, + echoCancellation: false, + autoGainControl: true, + noiseSuppression: true + }; + + const context = new AudioContext(audioContextOptions as any); + + const audioBuffer = await context.decodeAudioData(blobBuffer); + if (token.isCancellationRequested) { + return; + } + + const text = await this.voiceRecognitionService.transcribe({ + sampleRate: audioContextOptions.sampleRate, + channelCount: audioContextOptions.channelCount, + length: audioBuffer.length, + channelData: VSFloat32Array.wrap(audioBuffer.getChannelData(0)) + }); + + if (token.isCancellationRequested) { + return; + } + + emitter.fire(text); + } +} + +// Register Service +registerSingleton(IWorkbenchVoiceRecognitionService, WorkbenchVoiceRecognitionService, InstantiationType.Delayed); diff --git a/src/vs/workbench/workbench.desktop.main.ts b/src/vs/workbench/workbench.desktop.main.ts index e943de4afff..b3367ac6ea2 100644 --- a/src/vs/workbench/workbench.desktop.main.ts +++ b/src/vs/workbench/workbench.desktop.main.ts @@ -77,6 +77,8 @@ import 'vs/workbench/services/environment/electron-sandbox/shellEnvironmentServi import 'vs/workbench/services/integrity/electron-sandbox/integrityService'; import 'vs/workbench/services/workingCopy/electron-sandbox/workingCopyBackupService'; import 'vs/workbench/services/checksum/electron-sandbox/checksumService'; +import 'vs/workbench/services/voiceRecognition/electron-sandbox/voiceRecognitionService'; +import 'vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService'; import 'vs/platform/remote/electron-sandbox/sharedProcessTunnelService'; import 'vs/workbench/services/tunnel/electron-sandbox/tunnelService'; import 'vs/platform/diagnostics/electron-sandbox/diagnosticsService'; @@ -169,6 +171,9 @@ import 'vs/workbench/contrib/mergeEditor/electron-sandbox/mergeEditor.contributi // Remote Tunnel import 'vs/workbench/contrib/remoteTunnel/electron-sandbox/remoteTunnel.contribution'; +// Chat +import 'vs/workbench/contrib/chat/electron-sandbox/chat.contribution'; + //#endregion From 2eee37034d9c675a029495298c4fd3212f6c90bd Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 9 Aug 2023 07:53:03 +0200 Subject: [PATCH 003/221] voice - reuse `AudioContext` --- .../workbenchVoiceRecognitionService.ts | 32 ++++++++++--------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts b/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts index a98131381ce..43ff05ece57 100644 --- a/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts +++ b/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts @@ -42,6 +42,8 @@ export class WorkbenchVoiceRecognitionService implements IWorkbenchVoiceRecognit declare readonly _serviceBrand: undefined; private static readonly AUDIO_TIME_SLICE = 2000; + private static readonly AUDIO_SAMPLE_RATE = 16000; + private static readonly AUDIO_CHANNELS = 1; private static readonly AUDIO_MIME_TYPE = 'audio/webm;codecs=opus'; constructor( @@ -74,7 +76,7 @@ export class WorkbenchVoiceRecognitionService implements IWorkbenchVoiceRecognit return; } - const audioRecorder = new MediaRecorder(audioDevice, { mimeType: WorkbenchVoiceRecognitionService.AUDIO_MIME_TYPE }); + const audioRecorder = new MediaRecorder(audioDevice, { mimeType: WorkbenchVoiceRecognitionService.AUDIO_MIME_TYPE, audioBitsPerSecond: WorkbenchVoiceRecognitionService.AUDIO_SAMPLE_RATE }); audioRecorder.start(WorkbenchVoiceRecognitionService.AUDIO_TIME_SLICE); token.onCancellationRequested(() => { @@ -84,18 +86,28 @@ export class WorkbenchVoiceRecognitionService implements IWorkbenchVoiceRecognit progress.report({ message: localize('voiceTranscriptionRecording', "Recording from microphone...") }); + const audioContextOptions = { + sampleRate: WorkbenchVoiceRecognitionService.AUDIO_SAMPLE_RATE, + channelCount: WorkbenchVoiceRecognitionService.AUDIO_CHANNELS, + echoCancellation: false, + autoGainControl: true, + noiseSuppression: true + }; + + const context = new AudioContext(audioContextOptions as any); + const chunks: Blob[] = []; audioRecorder.ondataavailable = e => { chunks.push(e.data); - this.doTranscribeChunk(chunks, emitter, token); + this.doTranscribeChunk(context, chunks, emitter, token); }; return recordingDone.p; }); } - private async doTranscribeChunk(chunks: Blob[], emitter: Emitter, token: CancellationToken): Promise { + private async doTranscribeChunk(context: AudioContext, chunks: Blob[], emitter: Emitter, token: CancellationToken): Promise { if (token.isCancellationRequested) { return; } @@ -106,24 +118,14 @@ export class WorkbenchVoiceRecognitionService implements IWorkbenchVoiceRecognit return; } - const audioContextOptions = { - sampleRate: 16000 as const, - channelCount: 1 as const, - echoCancellation: false, - autoGainControl: true, - noiseSuppression: true - }; - - const context = new AudioContext(audioContextOptions as any); - const audioBuffer = await context.decodeAudioData(blobBuffer); if (token.isCancellationRequested) { return; } const text = await this.voiceRecognitionService.transcribe({ - sampleRate: audioContextOptions.sampleRate, - channelCount: audioContextOptions.channelCount, + sampleRate: WorkbenchVoiceRecognitionService.AUDIO_SAMPLE_RATE, + channelCount: WorkbenchVoiceRecognitionService.AUDIO_CHANNELS, length: audioBuffer.length, channelData: VSFloat32Array.wrap(audioBuffer.getChannelData(0)) }); From 47f0356460be5dd265065b5e1064aaebc77843b5 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 9 Aug 2023 10:54:33 +0200 Subject: [PATCH 004/221] voice - strip out non-speech tokens --- .../voiceRecognition/node/voiceRecognitionService.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/vs/platform/voiceRecognition/node/voiceRecognitionService.ts b/src/vs/platform/voiceRecognition/node/voiceRecognitionService.ts index cb57192e299..687ce112473 100644 --- a/src/vs/platform/voiceRecognition/node/voiceRecognitionService.ts +++ b/src/vs/platform/voiceRecognition/node/voiceRecognitionService.ts @@ -22,13 +22,16 @@ export class VoiceRecognitionService implements IVoiceRecognitionService { throw new Error('Voice recognition not yet supported!'); } - const voiceModule: { transcribe: (audioBuffer: { channelCount: 1; length: number; sampleRate: 16000; channelData: Float32Array }) => Promise } = require.__$__nodeRequire(modulePath); + const voiceModule: { transcribe: (audioBuffer: { channelCount: 1; length: number; sampleRate: 16000; channelData: Float32Array }, options: { language: string | 'auto'; suppressNonSpeechTokens: boolean }) => Promise } = require.__$__nodeRequire(modulePath); const text = await voiceModule.transcribe({ channelCount: buffer.channelCount, length: buffer.length, sampleRate: buffer.sampleRate, channelData: buffer.channelData.buffer + }, { + language: 'en', + suppressNonSpeechTokens: true }); this.logService.info(`[voice] transcribe(${buffer.length}): End (text: "${text}"))`); From 8b199750a4941b2cd13773c079097a33f31ba3b6 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 9 Aug 2023 11:38:56 +0200 Subject: [PATCH 005/221] voice - some options tweaks --- .../common/voiceRecognitionService.ts | 1 + .../node/voiceRecognitionService.ts | 8 +++--- .../workbenchVoiceRecognitionService.ts | 26 +++++++++++-------- 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/src/vs/platform/voiceRecognition/common/voiceRecognitionService.ts b/src/vs/platform/voiceRecognition/common/voiceRecognitionService.ts index 0cc3310df97..42650f5924d 100644 --- a/src/vs/platform/voiceRecognition/common/voiceRecognitionService.ts +++ b/src/vs/platform/voiceRecognition/common/voiceRecognitionService.ts @@ -10,6 +10,7 @@ export const IVoiceRecognitionService = createDecorator { + const now = Date.now(); this.logService.info(`[voice] transcribe(${buffer.length}): Begin`); const modulePath = process.env.VSCODE_VOICE_MODULE_PATH; @@ -22,19 +23,20 @@ export class VoiceRecognitionService implements IVoiceRecognitionService { throw new Error('Voice recognition not yet supported!'); } - const voiceModule: { transcribe: (audioBuffer: { channelCount: 1; length: number; sampleRate: 16000; channelData: Float32Array }, options: { language: string | 'auto'; suppressNonSpeechTokens: boolean }) => Promise } = require.__$__nodeRequire(modulePath); + const voiceModule: { transcribe: (audioBuffer: { channelCount: 1; length: number; sampleRate: 16000; sampleSize: 16; channelData: Float32Array }, options: { language: string | 'auto'; suppressNonSpeechTokens: boolean }) => Promise } = require.__$__nodeRequire(modulePath); const text = await voiceModule.transcribe({ + sampleRate: buffer.sampleRate, + sampleSize: buffer.sampleSize, channelCount: buffer.channelCount, length: buffer.length, - sampleRate: buffer.sampleRate, channelData: buffer.channelData.buffer }, { language: 'en', suppressNonSpeechTokens: true }); - this.logService.info(`[voice] transcribe(${buffer.length}): End (text: "${text}"))`); + this.logService.info(`[voice] transcribe(${buffer.length}): End (text: "${text}", took: ${Date.now() - now}ms))`); return text; } diff --git a/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts b/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts index 43ff05ece57..ca0846c1c01 100644 --- a/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts +++ b/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts @@ -30,7 +30,6 @@ export interface IWorkbenchVoiceRecognitionService { // TODO@voice // - load `navigator.mediaDevices.getUserMedia` lazily on startup? or would it trigger a permission prompt? -// - figure out the ugly `any` cast for AudioContext // - how to prevent data processing accumulation when processing is slow? // - how to make this a singleton service that enables ref-counting on multiple callers? // - cancellation should flow to the shared process @@ -41,8 +40,9 @@ export class WorkbenchVoiceRecognitionService implements IWorkbenchVoiceRecognit declare readonly _serviceBrand: undefined; - private static readonly AUDIO_TIME_SLICE = 2000; + private static readonly AUDIO_TIME_SLICE = 4000; private static readonly AUDIO_SAMPLE_RATE = 16000; + private static readonly AUDIO_SAMPLE_SIZE = 16; private static readonly AUDIO_CHANNELS = 1; private static readonly AUDIO_MIME_TYPE = 'audio/webm;codecs=opus'; @@ -70,7 +70,15 @@ export class WorkbenchVoiceRecognitionService implements IWorkbenchVoiceRecognit progress.report({ message: localize('voiceTranscriptionGettingReady', "Getting microphone ready...") }); - const audioDevice = await navigator.mediaDevices.getUserMedia({ audio: true }); + const audioDevice = await navigator.mediaDevices.getUserMedia({ + audio: { + sampleRate: WorkbenchVoiceRecognitionService.AUDIO_SAMPLE_RATE, + sampleSize: WorkbenchVoiceRecognitionService.AUDIO_SAMPLE_SIZE, + channelCount: WorkbenchVoiceRecognitionService.AUDIO_CHANNELS, + autoGainControl: true, + noiseSuppression: true + } + }); if (token.isCancellationRequested) { return; @@ -86,15 +94,10 @@ export class WorkbenchVoiceRecognitionService implements IWorkbenchVoiceRecognit progress.report({ message: localize('voiceTranscriptionRecording', "Recording from microphone...") }); - const audioContextOptions = { + const context = new AudioContext({ sampleRate: WorkbenchVoiceRecognitionService.AUDIO_SAMPLE_RATE, - channelCount: WorkbenchVoiceRecognitionService.AUDIO_CHANNELS, - echoCancellation: false, - autoGainControl: true, - noiseSuppression: true - }; - - const context = new AudioContext(audioContextOptions as any); + latencyHint: 'interactive' + }); const chunks: Blob[] = []; audioRecorder.ondataavailable = e => { @@ -125,6 +128,7 @@ export class WorkbenchVoiceRecognitionService implements IWorkbenchVoiceRecognit const text = await this.voiceRecognitionService.transcribe({ sampleRate: WorkbenchVoiceRecognitionService.AUDIO_SAMPLE_RATE, + sampleSize: WorkbenchVoiceRecognitionService.AUDIO_SAMPLE_SIZE, channelCount: WorkbenchVoiceRecognitionService.AUDIO_CHANNELS, length: audioBuffer.length, channelData: VSFloat32Array.wrap(audioBuffer.getChannelData(0)) From ab9a1a4d77b7bab7be6a50599be56eb9bb1a082f Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 9 Aug 2023 15:25:42 +0200 Subject: [PATCH 006/221] voice - leverage audio worklet --- .../common/voiceRecognitionService.ts | 1 - .../node/voiceRecognitionService.ts | 7 +- .../electron-sandbox/chat.contribution.ts | 4 +- .../bufferInputAudioProcessor.js | 67 +++++++++++++++++++ .../workbenchVoiceRecognitionService.ts | 66 +++++++++--------- 5 files changed, 107 insertions(+), 38 deletions(-) create mode 100644 src/vs/workbench/services/voiceRecognition/electron-sandbox/bufferInputAudioProcessor.js diff --git a/src/vs/platform/voiceRecognition/common/voiceRecognitionService.ts b/src/vs/platform/voiceRecognition/common/voiceRecognitionService.ts index 42650f5924d..3accb99ed0a 100644 --- a/src/vs/platform/voiceRecognition/common/voiceRecognitionService.ts +++ b/src/vs/platform/voiceRecognition/common/voiceRecognitionService.ts @@ -12,7 +12,6 @@ export interface IAudioBuffer { readonly sampleRate: 16000; readonly sampleSize: 16; readonly channelCount: 1; - readonly length: number; readonly channelData: VSFloat32Array; } diff --git a/src/vs/platform/voiceRecognition/node/voiceRecognitionService.ts b/src/vs/platform/voiceRecognition/node/voiceRecognitionService.ts index 1e48102b675..a9c750ec97d 100644 --- a/src/vs/platform/voiceRecognition/node/voiceRecognitionService.ts +++ b/src/vs/platform/voiceRecognition/node/voiceRecognitionService.ts @@ -16,27 +16,26 @@ export class VoiceRecognitionService implements IVoiceRecognitionService { async transcribe(buffer: IAudioBuffer): Promise { const now = Date.now(); - this.logService.info(`[voice] transcribe(${buffer.length}): Begin`); + this.logService.info(`[voice] transcribe(${buffer.channelData.buffer.length}): Begin`); const modulePath = process.env.VSCODE_VOICE_MODULE_PATH; if (!modulePath) { throw new Error('Voice recognition not yet supported!'); } - const voiceModule: { transcribe: (audioBuffer: { channelCount: 1; length: number; sampleRate: 16000; sampleSize: 16; channelData: Float32Array }, options: { language: string | 'auto'; suppressNonSpeechTokens: boolean }) => Promise } = require.__$__nodeRequire(modulePath); + const voiceModule: { transcribe: (audioBuffer: { channelCount: 1; sampleRate: 16000; sampleSize: 16; channelData: Float32Array }, options: { language: string | 'auto'; suppressNonSpeechTokens: boolean }) => Promise } = require.__$__nodeRequire(modulePath); const text = await voiceModule.transcribe({ sampleRate: buffer.sampleRate, sampleSize: buffer.sampleSize, channelCount: buffer.channelCount, - length: buffer.length, channelData: buffer.channelData.buffer }, { language: 'en', suppressNonSpeechTokens: true }); - this.logService.info(`[voice] transcribe(${buffer.length}): End (text: "${text}", took: ${Date.now() - now}ms))`); + this.logService.info(`[voice] transcribe(${buffer.channelData.buffer.length}): End (text: "${text}", took: ${Date.now() - now}ms))`); return text; } diff --git a/src/vs/workbench/contrib/chat/electron-sandbox/chat.contribution.ts b/src/vs/workbench/contrib/chat/electron-sandbox/chat.contribution.ts index 0f0c9474e27..45bb21c29ef 100644 --- a/src/vs/workbench/contrib/chat/electron-sandbox/chat.contribution.ts +++ b/src/vs/workbench/contrib/chat/electron-sandbox/chat.contribution.ts @@ -44,7 +44,9 @@ CommandsRegistry.registerCommand('workbench.action.toggleVoiceTranscription', as activeVoiceTranscription.add(toDisposable(() => voiceTranscriptionNotification.close())); activeVoiceTranscription.add(voiceRecognitionService.transcribe(cts.token)(text => { - voiceTranscriptionNotification.updateMessage(text); + if (text) { + voiceTranscriptionNotification.updateMessage(text); + } })); } }); diff --git a/src/vs/workbench/services/voiceRecognition/electron-sandbox/bufferInputAudioProcessor.js b/src/vs/workbench/services/voiceRecognition/electron-sandbox/bufferInputAudioProcessor.js new file mode 100644 index 00000000000..bed2b6ea63c --- /dev/null +++ b/src/vs/workbench/services/voiceRecognition/electron-sandbox/bufferInputAudioProcessor.js @@ -0,0 +1,67 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +//@ts-check +'use strict'; + +// @ts-ignore +class BufferInputAudioProcessor extends AudioWorkletProcessor { + + constructor() { + super(); + + this.channelCount = 1; + this.bufferTimespan = 4000; + this.startTime = undefined; + + this.allInputChannelDataBuffer = undefined; + this.currentInputChannelDataBuffer = []; // buffer over the duration of bufferTimespan + } + + /** + * @param {[[Float32Array]]} inputs + */ + process(inputs) { + if (this.startTime === undefined) { + this.startTime = Date.now(); + } + + const inputChannelData = inputs[0][0]; + this.currentInputChannelDataBuffer.push(inputChannelData.slice(0)); + + if (Date.now() - this.startTime > this.bufferTimespan) { + const currentInputChannelDataBuffer = this.currentInputChannelDataBuffer; + this.currentInputChannelDataBuffer = []; + + this.allInputChannelDataBuffer = this._joinFloat32Arrays(this.allInputChannelDataBuffer ? [this.allInputChannelDataBuffer, ...currentInputChannelDataBuffer] : currentInputChannelDataBuffer); + + // @ts-ignore + this.port.postMessage(this.allInputChannelDataBuffer); + + this.startTime = Date.now(); + } + + return true; + } + + /** + * @param {Float32Array[]} float32Arrays + * @returns {Float32Array} + */ + _joinFloat32Arrays(float32Arrays) { + const result = new Float32Array(float32Arrays.reduce((acc, curr) => acc + curr.length, 0)); + + let offset = 0; + for (const float32Array of float32Arrays) { + result.set(float32Array, offset); + offset += float32Array.length; + } + + return result; + } +} + +// @ts-ignore +registerProcessor('buffer-input-audio-processor', BufferInputAudioProcessor); diff --git a/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts b/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts index ca0846c1c01..1e3c986de15 100644 --- a/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts +++ b/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts @@ -12,6 +12,7 @@ import { IVoiceRecognitionService } from 'vs/platform/voiceRecognition/common/vo import { Emitter, Event } from 'vs/base/common/event'; import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/progress'; import { DeferredPromise } from 'vs/base/common/async'; +import { FileAccess } from 'vs/base/common/network'; export const IWorkbenchVoiceRecognitionService = createDecorator('workbenchVoiceRecognitionService'); @@ -28,6 +29,12 @@ export interface IWorkbenchVoiceRecognitionService { transcribe(cancellation: CancellationToken): Event; } +class BufferInputAudioNode extends AudioWorkletNode { + constructor(context: BaseAudioContext, options: AudioWorkletNodeOptions) { + super(context, 'buffer-input-audio-processor', options); + } +} + // TODO@voice // - load `navigator.mediaDevices.getUserMedia` lazily on startup? or would it trigger a permission prompt? // - how to prevent data processing accumulation when processing is slow? @@ -40,11 +47,9 @@ export class WorkbenchVoiceRecognitionService implements IWorkbenchVoiceRecognit declare readonly _serviceBrand: undefined; - private static readonly AUDIO_TIME_SLICE = 4000; private static readonly AUDIO_SAMPLE_RATE = 16000; private static readonly AUDIO_SAMPLE_SIZE = 16; private static readonly AUDIO_CHANNELS = 1; - private static readonly AUDIO_MIME_TYPE = 'audio/webm;codecs=opus'; constructor( @IVoiceRecognitionService private readonly voiceRecognitionService: IVoiceRecognitionService, @@ -70,7 +75,7 @@ export class WorkbenchVoiceRecognitionService implements IWorkbenchVoiceRecognit progress.report({ message: localize('voiceTranscriptionGettingReady', "Getting microphone ready...") }); - const audioDevice = await navigator.mediaDevices.getUserMedia({ + const microphoneDevice = await navigator.mediaDevices.getUserMedia({ audio: { sampleRate: WorkbenchVoiceRecognitionService.AUDIO_SAMPLE_RATE, sampleSize: WorkbenchVoiceRecognitionService.AUDIO_SAMPLE_SIZE, @@ -84,44 +89,42 @@ export class WorkbenchVoiceRecognitionService implements IWorkbenchVoiceRecognit return; } - const audioRecorder = new MediaRecorder(audioDevice, { mimeType: WorkbenchVoiceRecognitionService.AUDIO_MIME_TYPE, audioBitsPerSecond: WorkbenchVoiceRecognitionService.AUDIO_SAMPLE_RATE }); - audioRecorder.start(WorkbenchVoiceRecognitionService.AUDIO_TIME_SLICE); - - token.onCancellationRequested(() => { - audioRecorder.stop(); - recordingDone.complete(); - }); - - progress.report({ message: localize('voiceTranscriptionRecording', "Recording from microphone...") }); - - const context = new AudioContext({ + const audioContext = new AudioContext({ sampleRate: WorkbenchVoiceRecognitionService.AUDIO_SAMPLE_RATE, latencyHint: 'interactive' }); - const chunks: Blob[] = []; - audioRecorder.ondataavailable = e => { - chunks.push(e.data); + const microphoneSource = audioContext.createMediaStreamSource(microphoneDevice); - this.doTranscribeChunk(context, chunks, emitter, token); + token.onCancellationRequested(() => { + microphoneDevice.getTracks().forEach(track => track.stop()); + microphoneSource.disconnect(); + audioContext.close(); + recordingDone.complete(); + }); + + await audioContext.audioWorklet.addModule(FileAccess.asBrowserUri('vs/workbench/services/voiceRecognition/electron-sandbox/bufferInputAudioProcessor.js').toString(true)); + + const bufferInputAudioTarget = new BufferInputAudioNode(audioContext, { + channelCount: WorkbenchVoiceRecognitionService.AUDIO_CHANNELS, + channelCountMode: 'explicit' + }); + + microphoneSource.connect(bufferInputAudioTarget); + + progress.report({ message: localize('voiceTranscriptionRecording', "Recording from microphone...") }); + + bufferInputAudioTarget.port.onmessage = async e => { + if (e.data instanceof Float32Array) { + this.doTranscribeChunk(e.data, emitter, token); + } }; return recordingDone.p; }); } - private async doTranscribeChunk(context: AudioContext, chunks: Blob[], emitter: Emitter, token: CancellationToken): Promise { - if (token.isCancellationRequested) { - return; - } - - const blob = new Blob(chunks); - const blobBuffer = await blob.arrayBuffer(); - if (token.isCancellationRequested) { - return; - } - - const audioBuffer = await context.decodeAudioData(blobBuffer); + private async doTranscribeChunk(data: Float32Array, emitter: Emitter, token: CancellationToken): Promise { if (token.isCancellationRequested) { return; } @@ -130,8 +133,7 @@ export class WorkbenchVoiceRecognitionService implements IWorkbenchVoiceRecognit sampleRate: WorkbenchVoiceRecognitionService.AUDIO_SAMPLE_RATE, sampleSize: WorkbenchVoiceRecognitionService.AUDIO_SAMPLE_SIZE, channelCount: WorkbenchVoiceRecognitionService.AUDIO_CHANNELS, - length: audioBuffer.length, - channelData: VSFloat32Array.wrap(audioBuffer.getChannelData(0)) + channelData: VSFloat32Array.wrap(data) }); if (token.isCancellationRequested) { From 652e2d069c57887ec97f3ebac29533e44919cf14 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 9 Aug 2023 20:28:46 +0200 Subject: [PATCH 007/221] voice - update build script includes --- build/gulpfile.reh.js | 4 ---- build/gulpfile.vscode.js | 3 +-- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/build/gulpfile.reh.js b/build/gulpfile.reh.js index a235f55c79e..592157f8d76 100644 --- a/build/gulpfile.reh.js +++ b/build/gulpfile.reh.js @@ -62,10 +62,6 @@ const serverResources = [ // Performance 'out-build/vs/base/common/performance.js', - // Watcher - 'out-build/vs/platform/files/**/*.exe', - 'out-build/vs/platform/files/**/*.md', - // Process monitor 'out-build/vs/base/node/cpuUsage.sh', 'out-build/vs/base/node/ps.sh', diff --git a/build/gulpfile.vscode.js b/build/gulpfile.vscode.js index 9505e8fe5ca..2093df79b16 100644 --- a/build/gulpfile.vscode.js +++ b/build/gulpfile.vscode.js @@ -72,10 +72,9 @@ const vscodeResources = [ 'out-build/vs/workbench/contrib/terminal/browser/media/*.sh', 'out-build/vs/workbench/contrib/terminal/browser/media/*.zsh', 'out-build/vs/workbench/contrib/webview/browser/pre/*.js', + 'out-build/vs/workbench/services/voiceRecognition/electron-sandbox/bufferInputAudioProcessor.js', 'out-build/vs/**/markdown.css', 'out-build/vs/workbench/contrib/tasks/**/*.json', - 'out-build/vs/platform/files/**/*.exe', - 'out-build/vs/platform/files/**/*.md', '!**/test/**' ]; From 03ffebe2fcd06034091f47d996c1ebae7329e327 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 10 Aug 2023 12:43:37 +0200 Subject: [PATCH 008/221] voice - drop `VSFloat32Array` and encode `float32` into a `VSBuffer` --- src/vs/base/common/buffer.ts | 32 ------------ src/vs/base/common/marshalling.ts | 3 +- src/vs/base/test/common/buffer.test.ts | 21 +------- .../node/sharedProcess/sharedProcessMain.ts | 1 - .../common/voiceRecognitionService.ts | 17 +++---- .../node/voiceRecognitionService.ts | 40 +++++++++++---- .../bufferInputAudioProcessor.js | 50 +++++++++++++------ .../workbenchVoiceRecognitionService.ts | 18 +++---- 8 files changed, 81 insertions(+), 101 deletions(-) diff --git a/src/vs/base/common/buffer.ts b/src/vs/base/common/buffer.ts index 1981217fd1c..08736ab8c0b 100644 --- a/src/vs/base/common/buffer.ts +++ b/src/vs/base/common/buffer.ts @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ import { Lazy } from 'vs/base/common/lazy'; -import { MarshalledId } from 'vs/base/common/marshallingIds'; import * as streams from 'vs/base/common/stream'; declare const Buffer: any; @@ -440,34 +439,3 @@ export function encodeBase64({ buffer }: VSBuffer, padded = true, urlSafe = fals return output; } - -export interface VSFloat32ArrayComponents { - readonly $mid: MarshalledId.Float32Array; - readonly values: number[]; -} - -export class VSFloat32Array { - - readonly buffer: Float32Array; - readonly byteLength: number; - - static wrap(actual: Float32Array): VSFloat32Array { - return new VSFloat32Array(actual); - } - - private constructor(buffer: Float32Array) { - this.buffer = buffer; - this.byteLength = this.buffer.byteLength; - } - - toJSON(): VSFloat32ArrayComponents { - return { - $mid: MarshalledId.Float32Array, - values: Array.from(this.buffer.map(value => value)) - }; - } - - static revive(raw: VSFloat32ArrayComponents): VSFloat32Array { - return VSFloat32Array.wrap(new Float32Array(raw.values)); - } -} diff --git a/src/vs/base/common/marshalling.ts b/src/vs/base/common/marshalling.ts index 087ad5d0f58..67a29703cdc 100644 --- a/src/vs/base/common/marshalling.ts +++ b/src/vs/base/common/marshalling.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { VSBuffer, VSFloat32Array } from 'vs/base/common/buffer'; +import { VSBuffer } from 'vs/base/common/buffer'; import { regExpFlags } from 'vs/base/common/strings'; import { URI, UriComponents } from 'vs/base/common/uri'; import { MarshalledId } from './marshallingIds'; @@ -54,7 +54,6 @@ export function revive(obj: any, depth = 0): Revived { case MarshalledId.Uri: return URI.revive(obj); case MarshalledId.Regexp: return new RegExp(obj.source, obj.flags); case MarshalledId.Date: return new Date(obj.source); - case MarshalledId.Float32Array: return VSFloat32Array.revive(obj); } if ( diff --git a/src/vs/base/test/common/buffer.test.ts b/src/vs/base/test/common/buffer.test.ts index 969a96d9303..5a37943b658 100644 --- a/src/vs/base/test/common/buffer.test.ts +++ b/src/vs/base/test/common/buffer.test.ts @@ -5,8 +5,7 @@ import * as assert from 'assert'; import { timeout } from 'vs/base/common/async'; -import { bufferedStreamToBuffer, bufferToReadable, bufferToStream, decodeBase64, encodeBase64, newWriteableBufferStream, readableToBuffer, streamToBuffer, VSBuffer, VSFloat32Array } from 'vs/base/common/buffer'; -import { parse, stringify } from 'vs/base/common/marshalling'; +import { bufferedStreamToBuffer, bufferToReadable, bufferToStream, decodeBase64, encodeBase64, newWriteableBufferStream, readableToBuffer, streamToBuffer, VSBuffer } from 'vs/base/common/buffer'; import { peekStream } from 'vs/base/common/stream'; suite('Buffer', () => { @@ -478,22 +477,4 @@ suite('Buffer', () => { assert.throws(() => decodeBase64('invalid!')); }); }); - - suite('Float32Array', () => { - - test('serialization', () => { - const array = new Float32Array(10); - for (let i = 0; i < array.length; i++) { - array[i] = i === 0 ? 0 : Math.random(); - } - - const buffer = VSFloat32Array.wrap(array); - const serialized = stringify(buffer); - const deserialized = parse(serialized); - - assert.ok(deserialized instanceof VSFloat32Array); - assert.deepStrictEqual(array, deserialized.buffer); - assert.deepStrictEqual(array.byteLength, deserialized.byteLength); - }); - }); }); diff --git a/src/vs/code/node/sharedProcess/sharedProcessMain.ts b/src/vs/code/node/sharedProcess/sharedProcessMain.ts index 7092cc2b8ec..85559f93147 100644 --- a/src/vs/code/node/sharedProcess/sharedProcessMain.ts +++ b/src/vs/code/node/sharedProcess/sharedProcessMain.ts @@ -3,7 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -/* eslint-disable local/code-layering, local/code-import-patterns */ import { hostname, release } from 'os'; import { toErrorMessage } from 'vs/base/common/errorMessage'; import { onUnexpectedError, setUnexpectedErrorHandler } from 'vs/base/common/errors'; diff --git a/src/vs/platform/voiceRecognition/common/voiceRecognitionService.ts b/src/vs/platform/voiceRecognition/common/voiceRecognitionService.ts index 3accb99ed0a..34f7c9add07 100644 --- a/src/vs/platform/voiceRecognition/common/voiceRecognitionService.ts +++ b/src/vs/platform/voiceRecognition/common/voiceRecognitionService.ts @@ -3,18 +3,11 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { VSFloat32Array } from 'vs/base/common/buffer'; +import { VSBuffer } from 'vs/base/common/buffer'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; export const IVoiceRecognitionService = createDecorator('voiceRecognitionService'); -export interface IAudioBuffer { - readonly sampleRate: 16000; - readonly sampleSize: 16; - readonly channelCount: 1; - readonly channelData: VSFloat32Array; -} - export interface IVoiceRecognitionService { readonly _serviceBrand: undefined; @@ -24,8 +17,10 @@ export interface IVoiceRecognitionService { * transcribe the spoken words into text. * * @param buffer the audio data obtained from - * the microphone as PCM 32-bit float mono in - * 16khz. + * the microphone as uncompressed PCM data: + * - 1 channel (mono) + * - 16khz sampling rate + * - 16bit sample size */ - transcribe(buffer: IAudioBuffer): Promise; + transcribe(buffer: VSBuffer): Promise; } diff --git a/src/vs/platform/voiceRecognition/node/voiceRecognitionService.ts b/src/vs/platform/voiceRecognition/node/voiceRecognitionService.ts index a9c750ec97d..5cc49cae3ab 100644 --- a/src/vs/platform/voiceRecognition/node/voiceRecognitionService.ts +++ b/src/vs/platform/voiceRecognition/node/voiceRecognitionService.ts @@ -3,8 +3,9 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { VSBuffer } from 'vs/base/common/buffer'; import { ILogService } from 'vs/platform/log/common/log'; -import { IAudioBuffer, IVoiceRecognitionService } from 'vs/platform/voiceRecognition/common/voiceRecognitionService'; +import { IVoiceRecognitionService } from 'vs/platform/voiceRecognition/common/voiceRecognitionService'; export class VoiceRecognitionService implements IVoiceRecognitionService { @@ -14,29 +15,50 @@ export class VoiceRecognitionService implements IVoiceRecognitionService { @ILogService private readonly logService: ILogService ) { } - async transcribe(buffer: IAudioBuffer): Promise { - const now = Date.now(); - this.logService.info(`[voice] transcribe(${buffer.channelData.buffer.length}): Begin`); + async transcribe(buffer: VSBuffer): Promise { + this.logService.info(`[voice] transcribe(${buffer.buffer.length / 4}): Begin`); const modulePath = process.env.VSCODE_VOICE_MODULE_PATH; if (!modulePath) { throw new Error('Voice recognition not yet supported!'); } + const now = Date.now(); + const channelData = this.toFloat32Array(buffer); + const conversionTime = Date.now() - now; + const voiceModule: { transcribe: (audioBuffer: { channelCount: 1; sampleRate: 16000; sampleSize: 16; channelData: Float32Array }, options: { language: string | 'auto'; suppressNonSpeechTokens: boolean }) => Promise } = require.__$__nodeRequire(modulePath); const text = await voiceModule.transcribe({ - sampleRate: buffer.sampleRate, - sampleSize: buffer.sampleSize, - channelCount: buffer.channelCount, - channelData: buffer.channelData.buffer + sampleRate: 16000, + sampleSize: 16, + channelCount: 1, + channelData }, { language: 'en', suppressNonSpeechTokens: true }); - this.logService.info(`[voice] transcribe(${buffer.channelData.buffer.length}): End (text: "${text}", took: ${Date.now() - now}ms))`); + this.logService.info(`[voice] transcribe(${buffer.buffer.length / 4}): End (text: "${text}", took: ${Date.now() - now}ms total, ${conversionTime}ms uint8->float32 conversion)`); return text; } + + private toFloat32Array({ buffer: uint8Array }: VSBuffer): Float32Array { + const float32Array = new Float32Array(uint8Array.length / 4); + let offset = 0; + + for (let i = 0; i < float32Array.length; i++) { + const buffer = new ArrayBuffer(4); + const view = new DataView(buffer); + + for (let j = 0; j < 4; j++) { + view.setUint8(j, uint8Array[offset++]); + } + + float32Array[i] = view.getFloat32(0, true); + } + + return float32Array; + } } diff --git a/src/vs/workbench/services/voiceRecognition/electron-sandbox/bufferInputAudioProcessor.js b/src/vs/workbench/services/voiceRecognition/electron-sandbox/bufferInputAudioProcessor.js index bed2b6ea63c..bc87ec89076 100644 --- a/src/vs/workbench/services/voiceRecognition/electron-sandbox/bufferInputAudioProcessor.js +++ b/src/vs/workbench/services/voiceRecognition/electron-sandbox/bufferInputAudioProcessor.js @@ -16,8 +16,8 @@ class BufferInputAudioProcessor extends AudioWorkletProcessor { this.bufferTimespan = 4000; this.startTime = undefined; - this.allInputChannelDataBuffer = undefined; - this.currentInputChannelDataBuffer = []; // buffer over the duration of bufferTimespan + this.allInputUint8Array = undefined; + this.currentInputUint8Arrays = []; // buffer over the duration of bufferTimespan } /** @@ -29,16 +29,16 @@ class BufferInputAudioProcessor extends AudioWorkletProcessor { } const inputChannelData = inputs[0][0]; - this.currentInputChannelDataBuffer.push(inputChannelData.slice(0)); + this.currentInputUint8Arrays.push(this.float32ArrayToUint8Array(inputChannelData.slice(0))); if (Date.now() - this.startTime > this.bufferTimespan) { - const currentInputChannelDataBuffer = this.currentInputChannelDataBuffer; - this.currentInputChannelDataBuffer = []; + const currentInputUint8Arrays = this.currentInputUint8Arrays; + this.currentInputUint8Arrays = []; - this.allInputChannelDataBuffer = this._joinFloat32Arrays(this.allInputChannelDataBuffer ? [this.allInputChannelDataBuffer, ...currentInputChannelDataBuffer] : currentInputChannelDataBuffer); + this.allInputUint8Array = this.joinUint8Arrays(this.allInputUint8Array ? [this.allInputUint8Array, ...currentInputUint8Arrays] : currentInputUint8Arrays); // @ts-ignore - this.port.postMessage(this.allInputChannelDataBuffer); + this.port.postMessage(this.allInputUint8Array); this.startTime = Date.now(); } @@ -47,20 +47,42 @@ class BufferInputAudioProcessor extends AudioWorkletProcessor { } /** - * @param {Float32Array[]} float32Arrays - * @returns {Float32Array} + * @param {Uint8Array[]} uint8Arrays + * @returns {Uint8Array} */ - _joinFloat32Arrays(float32Arrays) { - const result = new Float32Array(float32Arrays.reduce((acc, curr) => acc + curr.length, 0)); + joinUint8Arrays(uint8Arrays) { + const result = new Uint8Array(uint8Arrays.reduce((acc, curr) => acc + curr.length, 0)); let offset = 0; - for (const float32Array of float32Arrays) { - result.set(float32Array, offset); - offset += float32Array.length; + for (const uint8Array of uint8Arrays) { + result.set(uint8Array, offset); + offset += uint8Array.length; } return result; } + + /** + * + * @param {Float32Array} float32Array + * @returns {Uint8Array} + */ + float32ArrayToUint8Array(float32Array) { + const uint8Array = new Uint8Array(float32Array.length * 4); + let offset = 0; + + for (let i = 0; i < float32Array.length; i++) { + const buffer = new ArrayBuffer(4); + const view = new DataView(buffer); + view.setFloat32(0, float32Array[i], true); + + for (let j = 0; j < 4; j++) { + uint8Array[offset++] = view.getUint8(j); + } + } + + return uint8Array; + } } // @ts-ignore diff --git a/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts b/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts index 1e3c986de15..11dfe1c3d33 100644 --- a/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts +++ b/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { localize } from 'vs/nls'; -import { VSFloat32Array } from 'vs/base/common/buffer'; +import { VSBuffer } from 'vs/base/common/buffer'; import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation'; import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; @@ -36,12 +36,12 @@ class BufferInputAudioNode extends AudioWorkletNode { } // TODO@voice -// - load `navigator.mediaDevices.getUserMedia` lazily on startup? or would it trigger a permission prompt? // - how to prevent data processing accumulation when processing is slow? // - how to make this a singleton service that enables ref-counting on multiple callers? // - cancellation should flow to the shared process // - voice module should directly transcribe the PCM32 data -// - we should transfer the Float32Array directly without serialisation overhead +// - we should transfer the Float32Array directly without serialisation overhead maybe from AudioWorklet? +// - the audio worklet should be a TS file (try without any import/export?) export class WorkbenchVoiceRecognitionService implements IWorkbenchVoiceRecognitionService { @@ -115,7 +115,7 @@ export class WorkbenchVoiceRecognitionService implements IWorkbenchVoiceRecognit progress.report({ message: localize('voiceTranscriptionRecording', "Recording from microphone...") }); bufferInputAudioTarget.port.onmessage = async e => { - if (e.data instanceof Float32Array) { + if (e.data instanceof Uint8Array) { this.doTranscribeChunk(e.data, emitter, token); } }; @@ -124,18 +124,12 @@ export class WorkbenchVoiceRecognitionService implements IWorkbenchVoiceRecognit }); } - private async doTranscribeChunk(data: Float32Array, emitter: Emitter, token: CancellationToken): Promise { + private async doTranscribeChunk(data: Uint8Array, emitter: Emitter, token: CancellationToken): Promise { if (token.isCancellationRequested) { return; } - const text = await this.voiceRecognitionService.transcribe({ - sampleRate: WorkbenchVoiceRecognitionService.AUDIO_SAMPLE_RATE, - sampleSize: WorkbenchVoiceRecognitionService.AUDIO_SAMPLE_SIZE, - channelCount: WorkbenchVoiceRecognitionService.AUDIO_CHANNELS, - channelData: VSFloat32Array.wrap(data) - }); - + const text = await this.voiceRecognitionService.transcribe(VSBuffer.wrap(data)); if (token.isCancellationRequested) { return; } From 7e3f23966dd0f5fd7f084837ca359c864a3851f0 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 10 Aug 2023 15:43:44 +0200 Subject: [PATCH 009/221] voice - prevent wrong data assumptions in processor --- .../electron-sandbox/bufferInputAudioProcessor.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/vs/workbench/services/voiceRecognition/electron-sandbox/bufferInputAudioProcessor.js b/src/vs/workbench/services/voiceRecognition/electron-sandbox/bufferInputAudioProcessor.js index bc87ec89076..f1473538c68 100644 --- a/src/vs/workbench/services/voiceRecognition/electron-sandbox/bufferInputAudioProcessor.js +++ b/src/vs/workbench/services/voiceRecognition/electron-sandbox/bufferInputAudioProcessor.js @@ -29,6 +29,10 @@ class BufferInputAudioProcessor extends AudioWorkletProcessor { } const inputChannelData = inputs[0][0]; + if ((!(inputChannelData instanceof Float32Array))) { + return; + } + this.currentInputUint8Arrays.push(this.float32ArrayToUint8Array(inputChannelData.slice(0))); if (Date.now() - this.startTime > this.bufferTimespan) { From 286530af074343de1a5ce906613dc6f61e51f51f Mon Sep 17 00:00:00 2001 From: Antonio Date: Sat, 12 Aug 2023 00:28:32 +0300 Subject: [PATCH 010/221] fix: add missing pricing parameter to manifest schema --- .../services/extensions/common/extensionsRegistry.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/vs/workbench/services/extensions/common/extensionsRegistry.ts b/src/vs/workbench/services/extensions/common/extensionsRegistry.ts index 0df7ff16687..743f0a688d0 100644 --- a/src/vs/workbench/services/extensions/common/extensionsRegistry.ts +++ b/src/vs/workbench/services/extensions/common/extensionsRegistry.ts @@ -569,6 +569,12 @@ export const schema: IJSONSchema = { '{Locked="vscode.l10n API"}' ] }, 'The relative path to a folder containing localization (bundle.l10n.*.json) files. Must be specified if you are using the vscode.l10n API.') + }, + pricing: { + type: 'string', + markdownDescription: nls.localize('vscode.extension.pricing', 'The pricing information for the extension. Can be Free (default) or Trial. For more details visit: https://code.visualstudio.com/api/working-with-extensions/publishing-extension#extension-pricing-label'), + enum: ['Free', 'Trial'], + default: 'Free' } } }; From b4801aeb02735469083b40d00aafe7dbff075f62 Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Tue, 15 Aug 2023 12:20:02 +0200 Subject: [PATCH 011/221] adding the data relative to the diagnostic error codes in the typescript extension --- .../src/languageFeatures/diagnostics.ts | 28 ++++++++++++++++++- .../src/typescriptServiceClient.ts | 3 +- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts b/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts index aeb4491872e..5981e63ea6e 100644 --- a/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts +++ b/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts @@ -8,6 +8,7 @@ import { DiagnosticLanguage } from '../configuration/languageDescription'; import * as arrays from '../utils/arrays'; import { Disposable } from '../utils/dispose'; import { ResourceMap } from '../utils/resourceMap'; +import { TelemetryReporter } from '../logging/telemetry'; function diagnosticsEquals(a: vscode.Diagnostic, b: vscode.Diagnostic): boolean { if (a === b) { @@ -153,11 +154,13 @@ export class DiagnosticsManager extends Disposable { private readonly _settings = new DiagnosticSettings(); private readonly _currentDiagnostics: vscode.DiagnosticCollection; private readonly _pendingUpdates: ResourceMap; + private readonly _telemetryReporter: TelemetryReporter; private readonly _updateDelay = 50; constructor( owner: string, + telemetryReporter: TelemetryReporter, onCaseInsensitiveFileSystem: boolean ) { super(); @@ -165,6 +168,7 @@ export class DiagnosticsManager extends Disposable { this._pendingUpdates = new ResourceMap(undefined, { onCaseInsensitiveFileSystem }); this._currentDiagnostics = this._register(vscode.languages.createDiagnosticCollection(owner)); + this._telemetryReporter = telemetryReporter; } public override dispose() { @@ -238,7 +242,29 @@ export class DiagnosticsManager extends Disposable { } public getDiagnostics(file: vscode.Uri): ReadonlyArray { - return this._currentDiagnostics.get(file) || []; + const diagnostics = this._currentDiagnostics.get(file) || []; + const diagnoticCodes = diagnostics.reduce(function (result: number[], d: vscode.Diagnostic) { + const code = d.code; + if (typeof code === 'string' || typeof code === 'number') { + result.push(Number(code)); + } else if (code !== undefined) { + result.push(Number(code.value)); + } + return result; + }, []).sort(); + /* __GDPR__ + "typescript.diagnostics" : { + "owner": "@aiday-mar", + "diagnosticCodes" : { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" }, + "${include}": [ + "${TypeScriptCommonProperties}" + ] + } + */ + this._telemetryReporter.logTelemetry('typescript.diagnostics', { + diagnoticCodes: diagnoticCodes.join(', ') + }); + return diagnostics; } private scheduleDiagnosticsUpdate(file: vscode.Uri) { diff --git a/extensions/typescript-language-features/src/typescriptServiceClient.ts b/extensions/typescript-language-features/src/typescriptServiceClient.ts index 86c6bb8d9f1..c165f82db40 100644 --- a/extensions/typescript-language-features/src/typescriptServiceClient.ts +++ b/extensions/typescript-language-features/src/typescriptServiceClient.ts @@ -176,7 +176,6 @@ export default class TypeScriptServiceClient extends Disposable implements IType this.bufferSyncSupport = new BufferSyncSupport(this, allModeIds, onCaseInsenitiveFileSystem); this.onReady(() => { this.bufferSyncSupport.listen(); }); - this.diagnosticsManager = new DiagnosticsManager('typescript', onCaseInsenitiveFileSystem); this.bufferSyncSupport.onDelete(resource => { this.cancelInflightRequestsForResource(resource); this.diagnosticsManager.deleteAllDiagnosticsInFile(resource); @@ -213,7 +212,7 @@ export default class TypeScriptServiceClient extends Disposable implements IType } return this.apiVersion.fullVersionString; }); - + this.diagnosticsManager = new DiagnosticsManager('typescript', this.telemetryReporter, onCaseInsenitiveFileSystem); this.typescriptServerSpawner = new TypeScriptServerSpawner(this.versionProvider, this._versionManager, this.logDirectoryProvider, this.pluginPathsProvider, this.logger, this.telemetryReporter, this.tracer, this.processFactory); this._register(this.pluginManager.onDidUpdateConfig(update => { From ea816abae3b66dade07e554107d52d822bf1b63a Mon Sep 17 00:00:00 2001 From: Lucas Marioza Date: Tue, 15 Aug 2023 12:58:40 -0300 Subject: [PATCH 012/221] Ensure style element is added to shadowDOM components on colorizeElement --- src/vs/editor/standalone/browser/standaloneEditor.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/vs/editor/standalone/browser/standaloneEditor.ts b/src/vs/editor/standalone/browser/standaloneEditor.ts index 4ff53468f06..005e48ad530 100644 --- a/src/vs/editor/standalone/browser/standaloneEditor.ts +++ b/src/vs/editor/standalone/browser/standaloneEditor.ts @@ -352,8 +352,9 @@ export function createWebWorker(opts: IWebWorkerOptions): Mona export function colorizeElement(domNode: HTMLElement, options: IColorizerElementOptions): Promise { const languageService = StandaloneServices.get(ILanguageService); const themeService = StandaloneServices.get(IStandaloneThemeService); - themeService.registerEditorContainer(domNode); - return Colorizer.colorizeElement(themeService, languageService, domNode, options); + return Colorizer.colorizeElement(themeService, languageService, domNode, options).then(() => { + themeService.registerEditorContainer(domNode); + }); } /** From 02c388ce8896104e1560f009954e93361089f099 Mon Sep 17 00:00:00 2001 From: Kartik Raj Date: Tue, 15 Aug 2023 23:01:29 +0000 Subject: [PATCH 013/221] Update scoped environment collection API --- .../api/common/extHostExtensionService.ts | 1 - .../api/common/extHostTerminalService.ts | 17 ++++++++----- ...scode.proposed.envCollectionWorkspace.d.ts | 25 +++++++++++-------- 3 files changed, 26 insertions(+), 17 deletions(-) diff --git a/src/vs/workbench/api/common/extHostExtensionService.ts b/src/vs/workbench/api/common/extHostExtensionService.ts index 34e70b79107..0c35ea254f3 100644 --- a/src/vs/workbench/api/common/extHostExtensionService.ts +++ b/src/vs/workbench/api/common/extHostExtensionService.ts @@ -532,7 +532,6 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme return that.extensionRuntime; }, get environmentVariableCollection() { return that._extHostTerminalService.getEnvironmentVariableCollection(extensionDescription); }, - getEnvironmentVariableCollection(scope?: vscode.EnvironmentVariableScope) { return that._extHostTerminalService.getEnvironmentVariableCollection(extensionDescription, scope); }, get messagePassingProtocol() { if (!messagePassingProtocol) { if (!messagePort) { diff --git a/src/vs/workbench/api/common/extHostTerminalService.ts b/src/vs/workbench/api/common/extHostTerminalService.ts index d91e8fe990f..01d9c9a9201 100644 --- a/src/vs/workbench/api/common/extHostTerminalService.ts +++ b/src/vs/workbench/api/common/extHostTerminalService.ts @@ -51,8 +51,13 @@ export interface IExtHostTerminalService extends ExtHostTerminalServiceShape, ID registerLinkProvider(provider: vscode.TerminalLinkProvider): vscode.Disposable; registerProfileProvider(extension: IExtensionDescription, id: string, provider: vscode.TerminalProfileProvider): vscode.Disposable; registerTerminalQuickFixProvider(id: string, extensionId: string, provider: vscode.TerminalQuickFixProvider): vscode.Disposable; - getEnvironmentVariableCollection(extension: IExtensionDescription, scope?: vscode.EnvironmentVariableScope): vscode.EnvironmentVariableCollection; + getEnvironmentVariableCollection(extension: IExtensionDescription): IEnvironmentVariableCollection; } + +interface IEnvironmentVariableCollection extends vscode.EnvironmentVariableCollection { + getScoped(scope: vscode.EnvironmentVariableScope): vscode.EnvironmentVariableCollection; +} + export interface ITerminalInternalOptions { isFeatureTerminal?: boolean; useShellEnvironment?: boolean; @@ -850,13 +855,13 @@ export abstract class BaseExtHostTerminalService extends Disposable implements I return index; } - public getEnvironmentVariableCollection(extension: IExtensionDescription, scope?: vscode.EnvironmentVariableScope): vscode.EnvironmentVariableCollection { + public getEnvironmentVariableCollection(extension: IExtensionDescription): IEnvironmentVariableCollection { let collection = this._environmentVariableCollections.get(extension.identifier.value); if (!collection) { collection = new UnifiedEnvironmentVariableCollection(extension); this._setEnvironmentVariableCollection(extension.identifier.value, collection); } - return collection.getScopedEnvironmentVariableCollection(scope); + return collection.getScopedEnvironmentVariableCollection(undefined); } private _syncEnvironmentVariableCollection(extensionIdentifier: string, collection: UnifiedEnvironmentVariableCollection): void { @@ -923,7 +928,7 @@ class UnifiedEnvironmentVariableCollection { this.map = new Map(serialized); } - getScopedEnvironmentVariableCollection(scope: vscode.EnvironmentVariableScope | undefined): vscode.EnvironmentVariableCollection { + getScopedEnvironmentVariableCollection(scope: vscode.EnvironmentVariableScope | undefined): IEnvironmentVariableCollection { if (this._extension && scope) { // TODO: This should be removed when the env var extension API(s) are stabilized checkProposedApiEnabled(this._extension, 'envCollectionWorkspace'); @@ -1066,7 +1071,7 @@ class UnifiedEnvironmentVariableCollection { } } -class ScopedEnvironmentVariableCollection implements vscode.EnvironmentVariableCollection { +class ScopedEnvironmentVariableCollection implements IEnvironmentVariableCollection { public get persistent(): boolean { return this.collection.persistent; } public set persistent(value: boolean) { this.collection.persistent = value; @@ -1081,7 +1086,7 @@ class ScopedEnvironmentVariableCollection implements vscode.EnvironmentVariableC ) { } - getScopedEnvironmentVariableCollection(scope: vscode.EnvironmentVariableScope | undefined) { + getScoped(scope: vscode.EnvironmentVariableScope | undefined) { return this.collection.getScopedEnvironmentVariableCollection(scope); } diff --git a/src/vscode-dts/vscode.proposed.envCollectionWorkspace.d.ts b/src/vscode-dts/vscode.proposed.envCollectionWorkspace.d.ts index 73bd11df4e2..0f1f519a6bd 100644 --- a/src/vscode-dts/vscode.proposed.envCollectionWorkspace.d.ts +++ b/src/vscode-dts/vscode.proposed.envCollectionWorkspace.d.ts @@ -9,25 +9,30 @@ declare module 'vscode' { export interface ExtensionContext { /** - * Gets the extension's environment variable collection for this workspace, enabling changes - * to be applied to terminal environment variables. - * - * @deprecated Use {@link getEnvironmentVariableCollection} instead. + * Gets the extension's global environment variable collection for this workspace, enabling changes to be + * applied to terminal environment variables. */ - readonly environmentVariableCollection: EnvironmentVariableCollection; + readonly environmentVariableCollection: GlobalEnvironmentVariableCollection; + } + + interface GlobalEnvironmentVariableCollection extends EnvironmentVariableCollection { /** - * Gets the extension's environment variable collection for this scope, enabling changes - * to be applied to terminal environment variables. + * Gets scope-specific environment variable collection for the extension. This enables alterations to + * terminal environment variables solely within the designated scope, and is applied in addition to (and + * after) the global collection. + * + * Each object obtained through this method is isolated and does not impact objects for other scopes, + * including the global collection. * * @param scope The scope to which the environment variable collection applies to. */ - getEnvironmentVariableCollection(scope?: EnvironmentVariableScope): EnvironmentVariableCollection; + getScoped(scope: EnvironmentVariableScope): EnvironmentVariableCollection; } export type EnvironmentVariableScope = { /** - * Any specific workspace folder to get collection for. If unspecified, collection applicable to all workspace folders is returned. - */ + * Any specific workspace folder to get collection for. If unspecified, collection applicable to all workspace folders is returned. + */ workspaceFolder?: WorkspaceFolder; }; } From 61011c827c7722dc2b49a84c675e6009cf1e5a65 Mon Sep 17 00:00:00 2001 From: Kartik Raj Date: Tue, 15 Aug 2023 23:18:31 +0000 Subject: [PATCH 014/221] Fix compile errors --- .../vscode.proposed.envCollectionWorkspace.d.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/vscode-dts/vscode.proposed.envCollectionWorkspace.d.ts b/src/vscode-dts/vscode.proposed.envCollectionWorkspace.d.ts index 0f1f519a6bd..43f77834b64 100644 --- a/src/vscode-dts/vscode.proposed.envCollectionWorkspace.d.ts +++ b/src/vscode-dts/vscode.proposed.envCollectionWorkspace.d.ts @@ -7,15 +7,15 @@ declare module 'vscode' { // https://github.com/microsoft/vscode/issues/171173 - export interface ExtensionContext { - /** - * Gets the extension's global environment variable collection for this workspace, enabling changes to be - * applied to terminal environment variables. - */ - readonly environmentVariableCollection: GlobalEnvironmentVariableCollection; - } + // export interface ExtensionContext { + // /** + // * Gets the extension's global environment variable collection for this workspace, enabling changes to be + // * applied to terminal environment variables. + // */ + // readonly environmentVariableCollection: GlobalEnvironmentVariableCollection; + // } - interface GlobalEnvironmentVariableCollection extends EnvironmentVariableCollection { + export interface GlobalEnvironmentVariableCollection extends EnvironmentVariableCollection { /** * Gets scope-specific environment variable collection for the extension. This enables alterations to * terminal environment variables solely within the designated scope, and is applied in addition to (and From 7c577637e862ad563a57d324347c4bf4e727f5ea Mon Sep 17 00:00:00 2001 From: Kartik Raj Date: Tue, 15 Aug 2023 23:31:07 +0000 Subject: [PATCH 015/221] Fix test --- .../src/singlefolder-tests/terminal.test.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/terminal.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/terminal.test.ts index f8c8b806853..76408d2de77 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/terminal.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/terminal.test.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { deepStrictEqual, doesNotThrow, equal, ok, strictEqual, throws } from 'assert'; -import { commands, ConfigurationTarget, Disposable, env, EnvironmentVariableCollection, EnvironmentVariableMutator, EnvironmentVariableMutatorOptions, EnvironmentVariableMutatorType, EnvironmentVariableScope, EventEmitter, ExtensionContext, extensions, ExtensionTerminalOptions, Pseudoterminal, Terminal, TerminalDimensions, TerminalExitReason, TerminalOptions, TerminalState, UIKind, Uri, window, workspace } from 'vscode'; +import { commands, ConfigurationTarget, Disposable, env, EnvironmentVariableMutator, EnvironmentVariableMutatorOptions, EnvironmentVariableMutatorType, EventEmitter, ExtensionContext, extensions, ExtensionTerminalOptions, GlobalEnvironmentVariableCollection, Pseudoterminal, Terminal, TerminalDimensions, TerminalExitReason, TerminalOptions, TerminalState, UIKind, Uri, window, workspace } from 'vscode'; import { assertNoRpc, poll } from '../utils'; // Disable terminal tests: @@ -913,10 +913,10 @@ import { assertNoRpc, poll } from '../utils'; test('get and forEach should work (scope)', () => { // TODO: Remove cast once `envCollectionWorkspace` API is finalized. - const collection = extensionContext.environmentVariableCollection as (EnvironmentVariableCollection & { getScopedEnvironmentVariableCollection(scope: EnvironmentVariableScope): EnvironmentVariableCollection }); + const collection = extensionContext.environmentVariableCollection as GlobalEnvironmentVariableCollection; disposables.push({ dispose: () => collection.clear() }); const scope = { workspaceFolder: { uri: Uri.file('workspace1'), name: 'workspace1', index: 0 } }; - const scopedCollection = collection.getScopedEnvironmentVariableCollection(scope); + const scopedCollection = collection.getScoped(scope); scopedCollection.replace('A', 'scoped~a2~'); scopedCollection.append('B', 'scoped~b2~'); scopedCollection.prepend('C', 'scoped~c2~'); @@ -928,7 +928,7 @@ import { assertNoRpc, poll } from '../utils'; applyAtProcessCreation: true, applyAtShellIntegration: false }; - const expectedScopedCollection = collection.getScopedEnvironmentVariableCollection(scope); + const expectedScopedCollection = collection.getScoped(scope); deepStrictEqual(expectedScopedCollection.get('A'), { value: 'scoped~a2~', type: EnvironmentVariableMutatorType.Replace, options: defaultOptions }); deepStrictEqual(expectedScopedCollection.get('B'), { value: 'scoped~b2~', type: EnvironmentVariableMutatorType.Append, options: defaultOptions }); deepStrictEqual(expectedScopedCollection.get('C'), { value: 'scoped~c2~', type: EnvironmentVariableMutatorType.Prepend, options: defaultOptions }); From b96621b58c0ec2cfad8e848712d11f8c5bf30f84 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 17 Aug 2023 11:47:14 +0200 Subject: [PATCH 016/221] voice - implement direct `MessagePort` communcation between audio worklet and shared process --- build/gulpfile.vscode.js | 2 +- src/vs/base/parts/ipc/node/ipc.mp.ts | 25 ++++- .../sharedProcess/contrib/voiceTranscriber.ts | 40 ++++++++ .../node/sharedProcess/sharedProcessMain.ts | 49 +++++++--- .../platform/ipc/electron-sandbox/services.ts | 14 +++ .../sharedProcess/common/sharedProcess.ts | 20 ++++ .../electron-main/sharedProcess.ts | 34 ++++--- .../common/voiceRecognitionService.ts | 7 +- .../node/voiceRecognitionService.ts | 26 +----- .../electron-sandbox/sharedProcessService.ts | 16 +++- .../bufferInputAudioProcessor.js | 93 ------------------- .../bufferedVoiceTranscriber.js | 92 ++++++++++++++++++ .../voiceRecognitionService.ts | 9 -- .../workbenchVoiceRecognitionService.ts | 80 ++++++++-------- .../electron-sandbox/workbenchTestServices.ts | 2 + src/vs/workbench/workbench.desktop.main.ts | 1 - 16 files changed, 309 insertions(+), 201 deletions(-) create mode 100644 src/vs/code/node/sharedProcess/contrib/voiceTranscriber.ts create mode 100644 src/vs/platform/sharedProcess/common/sharedProcess.ts delete mode 100644 src/vs/workbench/services/voiceRecognition/electron-sandbox/bufferInputAudioProcessor.js create mode 100644 src/vs/workbench/services/voiceRecognition/electron-sandbox/bufferedVoiceTranscriber.js delete mode 100644 src/vs/workbench/services/voiceRecognition/electron-sandbox/voiceRecognitionService.ts diff --git a/build/gulpfile.vscode.js b/build/gulpfile.vscode.js index 2093df79b16..cd0a762dfa7 100644 --- a/build/gulpfile.vscode.js +++ b/build/gulpfile.vscode.js @@ -72,7 +72,7 @@ const vscodeResources = [ 'out-build/vs/workbench/contrib/terminal/browser/media/*.sh', 'out-build/vs/workbench/contrib/terminal/browser/media/*.zsh', 'out-build/vs/workbench/contrib/webview/browser/pre/*.js', - 'out-build/vs/workbench/services/voiceRecognition/electron-sandbox/bufferInputAudioProcessor.js', + 'out-build/vs/workbench/services/voiceRecognition/electron-sandbox/bufferedVoiceTranscriber.js', 'out-build/vs/**/markdown.css', 'out-build/vs/workbench/contrib/tasks/**/*.json', '!**/test/**' diff --git a/src/vs/base/parts/ipc/node/ipc.mp.ts b/src/vs/base/parts/ipc/node/ipc.mp.ts index a7cfc538d5e..1a8b107dc99 100644 --- a/src/vs/base/parts/ipc/node/ipc.mp.ts +++ b/src/vs/base/parts/ipc/node/ipc.mp.ts @@ -33,18 +33,35 @@ class Protocol implements IMessagePassingProtocol { } } +export interface IClientConnectionFilter { + + /** + * Allows to filter incoming messages to the + * server to handle them differently. + * + * @param e the message event to handle + * @returns `true` if the event was handled + * and should not be processed by the server. + */ + handled(e: MessageEvent): boolean; +} + /** * An implementation of a `IPCServer` on top of MessagePort style IPC communication. * The clients register themselves via Electron Utility Process IPC transfer. */ export class Server extends IPCServer { - private static getOnDidClientConnect(): Event { + private static getOnDidClientConnect(filter?: IClientConnectionFilter): Event { assertType(isUtilityProcess(process), 'Electron Utility Process'); const onCreateMessageChannel = new Emitter(); - process.parentPort.on('message', (e: Electron.MessageEvent) => { + process.parentPort.on('message', (e: MessageEvent) => { + if (filter?.handled(e)) { + return; + } + const port = firstOrDefault(e.ports); if (port) { onCreateMessageChannel.fire(port); @@ -66,8 +83,8 @@ export class Server extends IPCServer { }); } - constructor() { - super(Server.getOnDidClientConnect()); + constructor(filter?: IClientConnectionFilter) { + super(Server.getOnDidClientConnect(filter)); } } diff --git a/src/vs/code/node/sharedProcess/contrib/voiceTranscriber.ts b/src/vs/code/node/sharedProcess/contrib/voiceTranscriber.ts new file mode 100644 index 00000000000..cbd23de96c4 --- /dev/null +++ b/src/vs/code/node/sharedProcess/contrib/voiceTranscriber.ts @@ -0,0 +1,40 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Event } from 'vs/base/common/event'; +import { MessagePortMain, MessageEvent } from 'vs/base/parts/sandbox/node/electronTypes'; +import { Disposable, toDisposable } from 'vs/base/common/lifecycle'; +import { IVoiceRecognitionService } from 'vs/platform/voiceRecognition/common/voiceRecognitionService'; + +export class VoiceTranscriber extends Disposable { + + constructor( + private readonly onDidWindowConnectRaw: Event, + @IVoiceRecognitionService private readonly voiceRecognitionService: IVoiceRecognitionService, + ) { + super(); + + this.registerListeners(); + } + + private registerListeners(): void { + this._register(this.onDidWindowConnectRaw(port => { + const portHandler = async (e: MessageEvent) => { + if (!(e.data instanceof Float32Array)) { + return; + } + + const result = await this.voiceRecognitionService.transcribe(e.data); + + port.postMessage(result); + }; + + port.on('message', portHandler); + this._register(toDisposable(() => port.off('message', portHandler))); + + port.start(); + })); + } +} diff --git a/src/vs/code/node/sharedProcess/sharedProcessMain.ts b/src/vs/code/node/sharedProcess/sharedProcessMain.ts index 85559f93147..91e93fccc59 100644 --- a/src/vs/code/node/sharedProcess/sharedProcessMain.ts +++ b/src/vs/code/node/sharedProcess/sharedProcessMain.ts @@ -4,13 +4,16 @@ *--------------------------------------------------------------------------------------------*/ import { hostname, release } from 'os'; +import { MessagePortMain, MessageEvent } from 'vs/base/parts/sandbox/node/electronTypes'; import { toErrorMessage } from 'vs/base/common/errorMessage'; import { onUnexpectedError, setUnexpectedErrorHandler } from 'vs/base/common/errors'; import { combinedDisposable, Disposable, toDisposable } from 'vs/base/common/lifecycle'; import { Schemas } from 'vs/base/common/network'; import { URI } from 'vs/base/common/uri'; +import { firstOrDefault } from 'vs/base/common/arrays'; +import { Emitter } from 'vs/base/common/event'; import { ProxyChannel, StaticRouter } from 'vs/base/parts/ipc/common/ipc'; -import { Server as UtilityProcessMessagePortServer, once } from 'vs/base/parts/ipc/node/ipc.mp'; +import { IClientConnectionFilter, Server as UtilityProcessMessagePortServer, once } from 'vs/base/parts/ipc/node/ipc.mp'; import { CodeCacheCleaner } from 'vs/code/node/sharedProcess/contrib/codeCacheCleaner'; import { LanguagePackCachedDataCleaner } from 'vs/code/node/sharedProcess/contrib/languagePackCachedDataCleaner'; import { LocalizationsUpdater } from 'vs/code/node/sharedProcess/contrib/localizationsUpdater'; @@ -113,13 +116,17 @@ import { nodeSocketFactory } from 'vs/platform/remote/node/nodeSocketFactory'; import { NativeEnvironmentService } from 'vs/platform/environment/node/environmentService'; import { IVoiceRecognitionService } from 'vs/platform/voiceRecognition/common/voiceRecognitionService'; import { VoiceRecognitionService } from 'vs/platform/voiceRecognition/node/voiceRecognitionService'; +import { VoiceTranscriber } from 'vs/code/node/sharedProcess/contrib/voiceTranscriber'; +import { RawSharedProcessConnection, SharedProcessLifecycle } from 'vs/platform/sharedProcess/common/sharedProcess'; -class SharedProcessMain extends Disposable { +class SharedProcessMain extends Disposable implements IClientConnectionFilter { - private readonly server = this._register(new UtilityProcessMessagePortServer()); + private readonly server = this._register(new UtilityProcessMessagePortServer(this)); private lifecycleService: SharedProcessLifecycleService | undefined = undefined; + private readonly onDidWindowConnectRaw = this._register(new Emitter()); + constructor(private configuration: ISharedProcessConfiguration) { super(); @@ -139,7 +146,7 @@ class SharedProcessMain extends Disposable { } }; process.once('exit', onExit); - once(process.parentPort, 'vscode:electron-main->shared-process=exit', onExit); + once(process.parentPort, SharedProcessLifecycle.exit, onExit); } async init(): Promise { @@ -171,7 +178,8 @@ class SharedProcessMain extends Disposable { instantiationService.createInstance(LogsDataCleaner), instantiationService.createInstance(LocalizationsUpdater), instantiationService.createInstance(ExtensionsContributions), - instantiationService.createInstance(UserDataProfilesCleaner) + instantiationService.createInstance(UserDataProfilesCleaner), + instantiationService.createInstance(VoiceTranscriber, this.onDidWindowConnectRaw.event) )); } @@ -353,7 +361,7 @@ class SharedProcessMain extends Disposable { services.set(IRemoteTunnelService, new SyncDescriptor(RemoteTunnelService)); // Voice Recognition - services.set(IVoiceRecognitionService, new SyncDescriptor(VoiceRecognitionService, undefined, false /* proxied to other processes */)); + services.set(IVoiceRecognitionService, new SyncDescriptor(VoiceRecognitionService)); return new InstantiationService(services); } @@ -412,10 +420,6 @@ class SharedProcessMain extends Disposable { // Remote Tunnel const remoteTunnelChannel = ProxyChannel.fromService(accessor.get(IRemoteTunnelService)); this.server.registerChannel('remoteTunnel', remoteTunnelChannel); - - // Voice Recognition - const voiceRecognitionChannel = ProxyChannel.fromService(accessor.get(IVoiceRecognitionService)); - this.server.registerChannel('voiceRecognition', voiceRecognitionChannel); } private registerErrorHandler(logService: ILogService): void { @@ -434,6 +438,27 @@ class SharedProcessMain extends Disposable { logService.error(`[uncaught exception in sharedProcess]: ${message}`); }); } + + handled(e: MessageEvent): boolean { + + // This filter on message port messages will look for + // attempts of a window to connect raw to the shared + // process to handle these connections separate from + // our IPC based protocol. + + if (e.data !== RawSharedProcessConnection.response) { + return false; + } + + const port = firstOrDefault(e.ports); + if (port) { + this.onDidWindowConnectRaw.fire(port); + + return true; + } + + return false; + } } export async function main(configuration: ISharedProcessConfiguration): Promise { @@ -442,12 +467,12 @@ export async function main(configuration: ISharedProcessConfiguration): Promise< // ready to accept message ports as client connections const sharedProcess = new SharedProcessMain(configuration); - process.parentPort.postMessage('vscode:shared-process->electron-main=ipc-ready'); + process.parentPort.postMessage(SharedProcessLifecycle.ipcReady); // await initialization and signal this back to electron-main await sharedProcess.init(); - process.parentPort.postMessage('vscode:shared-process->electron-main=init-done'); + process.parentPort.postMessage(SharedProcessLifecycle.initDone); } process.parentPort.once('message', (e: Electron.MessageEvent) => { diff --git a/src/vs/platform/ipc/electron-sandbox/services.ts b/src/vs/platform/ipc/electron-sandbox/services.ts index 36921e83ef5..060ef30d96d 100644 --- a/src/vs/platform/ipc/electron-sandbox/services.ts +++ b/src/vs/platform/ipc/electron-sandbox/services.ts @@ -63,6 +63,20 @@ export function registerMainProcessRemoteService(id: ServiceIdentifier, ch export const ISharedProcessService = createDecorator('sharedProcessService'); export interface ISharedProcessService extends IRemoteService { + + /** + * Allows to create a `MessagePort` connection between the + * shared process and the renderer process. + * + * Use this only when you need raw IPC to the shared process + * via `postMessage` and `on('message')` of special data structures + * like typed arrays. + * + * Callers have to call `port.start()` after having installed + * listeners to enable the data flow. + */ + createRawConnection(): Promise; + notifyRestored(): void; } diff --git a/src/vs/platform/sharedProcess/common/sharedProcess.ts b/src/vs/platform/sharedProcess/common/sharedProcess.ts new file mode 100644 index 00000000000..7e443fffb12 --- /dev/null +++ b/src/vs/platform/sharedProcess/common/sharedProcess.ts @@ -0,0 +1,20 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +export const SharedProcessLifecycle = { + exit: 'vscode:electron-main->shared-process=exit', + ipcReady: 'vscode:shared-process->electron-main=ipc-ready', + initDone: 'vscode:shared-process->electron-main=init-done' +}; + +export const ChannelSharedProcessConnection = { + request: 'vscode:createChannelSharedProcessConnection', + response: 'vscode:createChannelSharedProcessConnectionResult' +}; + +export const RawSharedProcessConnection = { + request: 'vscode:createRawSharedProcessConnection', + response: 'vscode:createRawSharedProcessConnectionResult' +}; diff --git a/src/vs/platform/sharedProcess/electron-main/sharedProcess.ts b/src/vs/platform/sharedProcess/electron-main/sharedProcess.ts index 51dd9d611a3..ec41ba8cc7a 100644 --- a/src/vs/platform/sharedProcess/electron-main/sharedProcess.ts +++ b/src/vs/platform/sharedProcess/electron-main/sharedProcess.ts @@ -18,6 +18,7 @@ import { UtilityProcess } from 'vs/platform/utilityProcess/electron-main/utility import { NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils'; import { parseSharedProcessDebugPort } from 'vs/platform/environment/node/environmentService'; import { assertIsDefined } from 'vs/base/common/types'; +import { ChannelSharedProcessConnection, RawSharedProcessConnection, SharedProcessLifecycle } from 'vs/platform/sharedProcess/common/sharedProcess'; export class SharedProcess extends Disposable { @@ -41,15 +42,18 @@ export class SharedProcess extends Disposable { private registerListeners(): void { - // Shared process connections from workbench windows - validatedIpcMain.on('vscode:createSharedProcessMessageChannel', (e, nonce: string) => this.onWindowConnection(e, nonce)); + // Shared process channel connections from workbench windows + validatedIpcMain.on(ChannelSharedProcessConnection.request, (e, nonce: string) => this.onWindowConnection(e, nonce, ChannelSharedProcessConnection.response)); + + // Shared process raw connections from workbench windows + validatedIpcMain.on(RawSharedProcessConnection.request, (e, nonce: string) => this.onWindowConnection(e, nonce, RawSharedProcessConnection.response)); // Lifecycle this._register(this.lifecycleMainService.onWillShutdown(() => this.onWillShutdown())); } - private async onWindowConnection(e: IpcMainEvent, nonce: string): Promise { - this.logService.trace('[SharedProcess] on vscode:createSharedProcessMessageChannel'); + private async onWindowConnection(e: IpcMainEvent, nonce: string, responseChannel: string): Promise { + this.logService.trace(`[SharedProcess] onWindowConnection for: ${responseChannel}`); // release barrier if this is the first window connection if (!this.firstWindowConnectionBarrier.isOpen()) { @@ -62,8 +66,10 @@ export class SharedProcess extends Disposable { await this.whenReady(); - // connect to the shared process - const port = await this.connect(); + // connect to the shared process passing the responseChannel + // as payload to give a hint what the connection is about + + const port = await this.connect(responseChannel); // Check back if the requesting window meanwhile closed // Since shared process is delayed on startup there is @@ -75,13 +81,13 @@ export class SharedProcess extends Disposable { } // send the port back to the requesting window - e.sender.postMessage('vscode:createSharedProcessMessageChannelResult', nonce, [port]); + e.sender.postMessage(responseChannel, nonce, [port]); } private onWillShutdown(): void { this.logService.trace('[SharedProcess] onWillShutdown'); - this.utilityProcess?.postMessage('vscode:electron-main->shared-process=exit'); + this.utilityProcess?.postMessage(SharedProcessLifecycle.exit); this.utilityProcess = undefined; } @@ -98,9 +104,9 @@ export class SharedProcess extends Disposable { const whenReady = new DeferredPromise(); if (this.utilityProcess) { - this.utilityProcess.once('vscode:shared-process->electron-main=init-done', () => whenReady.complete()); + this.utilityProcess.once(SharedProcessLifecycle.initDone, () => whenReady.complete()); } else { - validatedIpcMain.once('vscode:shared-process->electron-main=init-done', () => whenReady.complete()); + validatedIpcMain.once(SharedProcessLifecycle.initDone, () => whenReady.complete()); } await whenReady.p; @@ -125,9 +131,9 @@ export class SharedProcess extends Disposable { // Wait for shared process indicating that IPC connections are accepted const sharedProcessIpcReady = new DeferredPromise(); if (this.utilityProcess) { - this.utilityProcess.once('vscode:shared-process->electron-main=ipc-ready', () => sharedProcessIpcReady.complete()); + this.utilityProcess.once(SharedProcessLifecycle.ipcReady, () => sharedProcessIpcReady.complete()); } else { - validatedIpcMain.once('vscode:shared-process->electron-main=ipc-ready', () => sharedProcessIpcReady.complete()); + validatedIpcMain.once(SharedProcessLifecycle.ipcReady, () => sharedProcessIpcReady.complete()); } await sharedProcessIpcReady.p; @@ -175,13 +181,13 @@ export class SharedProcess extends Disposable { }; } - async connect(): Promise { + async connect(payload?: unknown): Promise { // Wait for shared process being ready to accept connection await this.whenIpcReady; // Connect and return message port const utilityProcess = assertIsDefined(this.utilityProcess); - return utilityProcess.connect(); + return utilityProcess.connect(payload); } } diff --git a/src/vs/platform/voiceRecognition/common/voiceRecognitionService.ts b/src/vs/platform/voiceRecognition/common/voiceRecognitionService.ts index 34f7c9add07..a563a2e45cd 100644 --- a/src/vs/platform/voiceRecognition/common/voiceRecognitionService.ts +++ b/src/vs/platform/voiceRecognition/common/voiceRecognitionService.ts @@ -3,7 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { VSBuffer } from 'vs/base/common/buffer'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; export const IVoiceRecognitionService = createDecorator('voiceRecognitionService'); @@ -16,11 +15,11 @@ export interface IVoiceRecognitionService { * Given a buffer of audio data, attempts to * transcribe the spoken words into text. * - * @param buffer the audio data obtained from - * the microphone as uncompressed PCM data: + * @param channelData the raw audio data obtained + * from the microphone as uncompressed PCM data: * - 1 channel (mono) * - 16khz sampling rate * - 16bit sample size */ - transcribe(buffer: VSBuffer): Promise; + transcribe(channelData: Float32Array): Promise; } diff --git a/src/vs/platform/voiceRecognition/node/voiceRecognitionService.ts b/src/vs/platform/voiceRecognition/node/voiceRecognitionService.ts index 5cc49cae3ab..a67fb2c54b4 100644 --- a/src/vs/platform/voiceRecognition/node/voiceRecognitionService.ts +++ b/src/vs/platform/voiceRecognition/node/voiceRecognitionService.ts @@ -3,7 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { VSBuffer } from 'vs/base/common/buffer'; import { ILogService } from 'vs/platform/log/common/log'; import { IVoiceRecognitionService } from 'vs/platform/voiceRecognition/common/voiceRecognitionService'; @@ -15,8 +14,8 @@ export class VoiceRecognitionService implements IVoiceRecognitionService { @ILogService private readonly logService: ILogService ) { } - async transcribe(buffer: VSBuffer): Promise { - this.logService.info(`[voice] transcribe(${buffer.buffer.length / 4}): Begin`); + async transcribe(channelData: Float32Array): Promise { + this.logService.info(`[voice] transcribe(${channelData.length}): Begin`); const modulePath = process.env.VSCODE_VOICE_MODULE_PATH; if (!modulePath) { @@ -24,7 +23,6 @@ export class VoiceRecognitionService implements IVoiceRecognitionService { } const now = Date.now(); - const channelData = this.toFloat32Array(buffer); const conversionTime = Date.now() - now; const voiceModule: { transcribe: (audioBuffer: { channelCount: 1; sampleRate: 16000; sampleSize: 16; channelData: Float32Array }, options: { language: string | 'auto'; suppressNonSpeechTokens: boolean }) => Promise } = require.__$__nodeRequire(modulePath); @@ -39,26 +37,8 @@ export class VoiceRecognitionService implements IVoiceRecognitionService { suppressNonSpeechTokens: true }); - this.logService.info(`[voice] transcribe(${buffer.buffer.length / 4}): End (text: "${text}", took: ${Date.now() - now}ms total, ${conversionTime}ms uint8->float32 conversion)`); + this.logService.info(`[voice] transcribe(${channelData.length}): End (text: "${text}", took: ${Date.now() - now}ms total, ${conversionTime}ms uint8->float32 conversion)`); return text; } - - private toFloat32Array({ buffer: uint8Array }: VSBuffer): Float32Array { - const float32Array = new Float32Array(uint8Array.length / 4); - let offset = 0; - - for (let i = 0; i < float32Array.length; i++) { - const buffer = new ArrayBuffer(4); - const view = new DataView(buffer); - - for (let j = 0; j < 4; j++) { - view.setUint8(j, uint8Array[offset++]); - } - - float32Array[i] = view.getFloat32(0, true); - } - - return float32Array; - } } diff --git a/src/vs/workbench/services/sharedProcess/electron-sandbox/sharedProcessService.ts b/src/vs/workbench/services/sharedProcess/electron-sandbox/sharedProcessService.ts index ce810b44b05..11a2fd6a72b 100644 --- a/src/vs/workbench/services/sharedProcess/electron-sandbox/sharedProcessService.ts +++ b/src/vs/workbench/services/sharedProcess/electron-sandbox/sharedProcessService.ts @@ -8,6 +8,7 @@ import { IChannel, IServerChannel, getDelayedChannel } from 'vs/base/parts/ipc/c import { ILogService } from 'vs/platform/log/common/log'; import { Disposable } from 'vs/base/common/lifecycle'; import { ISharedProcessService } from 'vs/platform/ipc/electron-sandbox/services'; +import { ChannelSharedProcessConnection, RawSharedProcessConnection } from 'vs/platform/sharedProcess/common/sharedProcess'; import { mark } from 'vs/base/common/performance'; import { Barrier, timeout } from 'vs/base/common/async'; import { acquirePort } from 'vs/base/parts/ipc/electron-sandbox/ipc.mp'; @@ -44,7 +45,7 @@ export class SharedProcessService extends Disposable implements ISharedProcessSe // Acquire a message port connected to the shared process mark('code/willConnectSharedProcess'); this.logService.trace('Renderer->SharedProcess#connect: before acquirePort'); - const port = await acquirePort('vscode:createSharedProcessMessageChannel', 'vscode:createSharedProcessMessageChannelResult'); + const port = await acquirePort(ChannelSharedProcessConnection.request, ChannelSharedProcessConnection.response); mark('code/didConnectSharedProcess'); this.logService.trace('Renderer->SharedProcess#connect: connection established'); @@ -64,4 +65,17 @@ export class SharedProcessService extends Disposable implements ISharedProcessSe registerChannel(channelName: string, channel: IServerChannel): void { this.withSharedProcessConnection.then(connection => connection.registerChannel(channelName, channel)); } + + async createRawConnection(): Promise { + + // Await initialization of the shared process + await this.connect(); + + // Create a new port to the shared process + this.logService.trace('Renderer->SharedProcess#createRawConnection: before acquirePort'); + const port = await acquirePort(RawSharedProcessConnection.request, RawSharedProcessConnection.response); + this.logService.trace('Renderer->SharedProcess#createRawConnection: connection established'); + + return port; + } } diff --git a/src/vs/workbench/services/voiceRecognition/electron-sandbox/bufferInputAudioProcessor.js b/src/vs/workbench/services/voiceRecognition/electron-sandbox/bufferInputAudioProcessor.js deleted file mode 100644 index f1473538c68..00000000000 --- a/src/vs/workbench/services/voiceRecognition/electron-sandbox/bufferInputAudioProcessor.js +++ /dev/null @@ -1,93 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -//@ts-check -'use strict'; - -// @ts-ignore -class BufferInputAudioProcessor extends AudioWorkletProcessor { - - constructor() { - super(); - - this.channelCount = 1; - this.bufferTimespan = 4000; - this.startTime = undefined; - - this.allInputUint8Array = undefined; - this.currentInputUint8Arrays = []; // buffer over the duration of bufferTimespan - } - - /** - * @param {[[Float32Array]]} inputs - */ - process(inputs) { - if (this.startTime === undefined) { - this.startTime = Date.now(); - } - - const inputChannelData = inputs[0][0]; - if ((!(inputChannelData instanceof Float32Array))) { - return; - } - - this.currentInputUint8Arrays.push(this.float32ArrayToUint8Array(inputChannelData.slice(0))); - - if (Date.now() - this.startTime > this.bufferTimespan) { - const currentInputUint8Arrays = this.currentInputUint8Arrays; - this.currentInputUint8Arrays = []; - - this.allInputUint8Array = this.joinUint8Arrays(this.allInputUint8Array ? [this.allInputUint8Array, ...currentInputUint8Arrays] : currentInputUint8Arrays); - - // @ts-ignore - this.port.postMessage(this.allInputUint8Array); - - this.startTime = Date.now(); - } - - return true; - } - - /** - * @param {Uint8Array[]} uint8Arrays - * @returns {Uint8Array} - */ - joinUint8Arrays(uint8Arrays) { - const result = new Uint8Array(uint8Arrays.reduce((acc, curr) => acc + curr.length, 0)); - - let offset = 0; - for (const uint8Array of uint8Arrays) { - result.set(uint8Array, offset); - offset += uint8Array.length; - } - - return result; - } - - /** - * - * @param {Float32Array} float32Array - * @returns {Uint8Array} - */ - float32ArrayToUint8Array(float32Array) { - const uint8Array = new Uint8Array(float32Array.length * 4); - let offset = 0; - - for (let i = 0; i < float32Array.length; i++) { - const buffer = new ArrayBuffer(4); - const view = new DataView(buffer); - view.setFloat32(0, float32Array[i], true); - - for (let j = 0; j < 4; j++) { - uint8Array[offset++] = view.getUint8(j); - } - } - - return uint8Array; - } -} - -// @ts-ignore -registerProcessor('buffer-input-audio-processor', BufferInputAudioProcessor); diff --git a/src/vs/workbench/services/voiceRecognition/electron-sandbox/bufferedVoiceTranscriber.js b/src/vs/workbench/services/voiceRecognition/electron-sandbox/bufferedVoiceTranscriber.js new file mode 100644 index 00000000000..3e4d6641c22 --- /dev/null +++ b/src/vs/workbench/services/voiceRecognition/electron-sandbox/bufferedVoiceTranscriber.js @@ -0,0 +1,92 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +//@ts-check +'use strict'; + +// @ts-ignore +class BufferedVoiceTranscriber extends AudioWorkletProcessor { + + constructor() { + super(); + + this.channelCount = 1; + this.bufferTimespan = 4000; + this.startTime = undefined; + + this.allInputFloat32Array = undefined; + this.currentInputFloat32Arrays = []; // buffer over the duration of bufferTimespan + + this.registerListeners(); + } + + registerListeners() { + + // @ts-ignore + const port = this.port; + port.onmessage = event => { + if (event.data === 'vscode:transferPortToAudioWorklet') { + this.sharedProcessPort = event.ports[0]; + + this.sharedProcessPort.onmessage = event => { + if (typeof event.data === 'string') { + port.postMessage(event.data); + } + }; + + this.sharedProcessPort.start(); + } + }; + } + + /** + * @param {[[Float32Array]]} inputs + */ + process(inputs) { + if (this.startTime === undefined) { + this.startTime = Date.now(); + } + + const inputChannelData = inputs[0][0]; + if ((!(inputChannelData instanceof Float32Array))) { + return; + } + + this.currentInputFloat32Arrays.push(inputChannelData.slice(0)); + + if (Date.now() - this.startTime > this.bufferTimespan && this.sharedProcessPort) { + const currentInputFloat32Arrays = this.currentInputFloat32Arrays; + this.currentInputFloat32Arrays = []; + + this.allInputFloat32Array = this.joinFloat32Arrays(this.allInputFloat32Array ? [this.allInputFloat32Array, ...currentInputFloat32Arrays] : currentInputFloat32Arrays); + + // @ts-ignore + this.sharedProcessPort.postMessage(this.allInputFloat32Array); + + this.startTime = Date.now(); + } + + return true; + } + + /** + * @param {Float32Array[]} float32Arrays + * @returns {Float32Array} + */ + joinFloat32Arrays(float32Arrays) { + const result = new Float32Array(float32Arrays.reduce((acc, curr) => acc + curr.length, 0)); + + let offset = 0; + for (const float32Array of float32Arrays) { + result.set(float32Array, offset); + offset += float32Array.length; + } + + return result; + } +} + +// @ts-ignore +registerProcessor('buffered-voice-transcriber', BufferedVoiceTranscriber); diff --git a/src/vs/workbench/services/voiceRecognition/electron-sandbox/voiceRecognitionService.ts b/src/vs/workbench/services/voiceRecognition/electron-sandbox/voiceRecognitionService.ts deleted file mode 100644 index e8b4e771ffa..00000000000 --- a/src/vs/workbench/services/voiceRecognition/electron-sandbox/voiceRecognitionService.ts +++ /dev/null @@ -1,9 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { registerSharedProcessRemoteService } from 'vs/platform/ipc/electron-sandbox/services'; -import { IVoiceRecognitionService } from 'vs/platform/voiceRecognition/common/voiceRecognitionService'; - -registerSharedProcessRemoteService(IVoiceRecognitionService, 'voiceRecognition'); diff --git a/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts b/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts index 11dfe1c3d33..523b07d1066 100644 --- a/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts +++ b/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts @@ -4,15 +4,14 @@ *--------------------------------------------------------------------------------------------*/ import { localize } from 'vs/nls'; -import { VSBuffer } from 'vs/base/common/buffer'; -import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation'; +import { CancellationToken } from 'vs/base/common/cancellation'; import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; -import { IVoiceRecognitionService } from 'vs/platform/voiceRecognition/common/voiceRecognitionService'; import { Emitter, Event } from 'vs/base/common/event'; import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/progress'; import { DeferredPromise } from 'vs/base/common/async'; import { FileAccess } from 'vs/base/common/network'; +import { ISharedProcessService } from 'vs/platform/ipc/electron-sandbox/services'; export const IWorkbenchVoiceRecognitionService = createDecorator('workbenchVoiceRecognitionService'); @@ -29,9 +28,32 @@ export interface IWorkbenchVoiceRecognitionService { transcribe(cancellation: CancellationToken): Event; } -class BufferInputAudioNode extends AudioWorkletNode { - constructor(context: BaseAudioContext, options: AudioWorkletNodeOptions) { - super(context, 'buffer-input-audio-processor', options); +class BufferedVoiceTranscriber extends AudioWorkletNode { + + constructor( + context: BaseAudioContext, + options: AudioWorkletNodeOptions, + private readonly onDidTranscribe: Emitter, + private readonly sharedProcessService: ISharedProcessService + ) { + super(context, 'buffered-voice-transcriber', options); + + this.registerListeners(); + } + + private registerListeners(): void { + this.port.onmessage = e => { + if (typeof e.data === 'string') { + this.onDidTranscribe.fire(e.data); + } + }; + } + + async start(token: CancellationToken): Promise { + const rawSharedProcessConnection = await this.sharedProcessService.createRawConnection(); + token.onCancellationRequested(() => rawSharedProcessConnection.close()); + + this.port.postMessage('vscode:transferPortToAudioWorklet', [rawSharedProcessConnection]); } } @@ -39,8 +61,7 @@ class BufferInputAudioNode extends AudioWorkletNode { // - how to prevent data processing accumulation when processing is slow? // - how to make this a singleton service that enables ref-counting on multiple callers? // - cancellation should flow to the shared process -// - voice module should directly transcribe the PCM32 data -// - we should transfer the Float32Array directly without serialisation overhead maybe from AudioWorklet? +// - voice module should directly transcribe the PCM32 data without wav+file conversion // - the audio worklet should be a TS file (try without any import/export?) export class WorkbenchVoiceRecognitionService implements IWorkbenchVoiceRecognitionService { @@ -52,21 +73,20 @@ export class WorkbenchVoiceRecognitionService implements IWorkbenchVoiceRecognit private static readonly AUDIO_CHANNELS = 1; constructor( - @IVoiceRecognitionService private readonly voiceRecognitionService: IVoiceRecognitionService, - @IProgressService private readonly progressService: IProgressService + @IProgressService private readonly progressService: IProgressService, + @ISharedProcessService private readonly sharedProcessService: ISharedProcessService ) { } transcribe(cancellation: CancellationToken): Event { - const cts = new CancellationTokenSource(cancellation); - const emitter = new Emitter(); - cancellation.onCancellationRequested(() => emitter.dispose()); + const onDidTranscribe = new Emitter(); + cancellation.onCancellationRequested(() => onDidTranscribe.dispose()); - this.doTranscribe(emitter, cts.token); + this.doTranscribe(onDidTranscribe, cancellation); - return emitter.event; + return onDidTranscribe.event; } - private async doTranscribe(emitter: Emitter, token: CancellationToken): Promise { + private async doTranscribe(onDidTranscribe: Emitter, token: CancellationToken): Promise { return this.progressService.withProgress({ location: ProgressLocation.Window, title: localize('voiceTranscription', "Voice Transcription"), @@ -103,39 +123,21 @@ export class WorkbenchVoiceRecognitionService implements IWorkbenchVoiceRecognit recordingDone.complete(); }); - await audioContext.audioWorklet.addModule(FileAccess.asBrowserUri('vs/workbench/services/voiceRecognition/electron-sandbox/bufferInputAudioProcessor.js').toString(true)); + await audioContext.audioWorklet.addModule(FileAccess.asBrowserUri('vs/workbench/services/voiceRecognition/electron-sandbox/bufferedVoiceTranscriber.js').toString(true)); - const bufferInputAudioTarget = new BufferInputAudioNode(audioContext, { + const bufferedVoiceTranscriberTarget = new BufferedVoiceTranscriber(audioContext, { channelCount: WorkbenchVoiceRecognitionService.AUDIO_CHANNELS, channelCountMode: 'explicit' - }); + }, onDidTranscribe, this.sharedProcessService); + await bufferedVoiceTranscriberTarget.start(token); - microphoneSource.connect(bufferInputAudioTarget); + microphoneSource.connect(bufferedVoiceTranscriberTarget); progress.report({ message: localize('voiceTranscriptionRecording', "Recording from microphone...") }); - bufferInputAudioTarget.port.onmessage = async e => { - if (e.data instanceof Uint8Array) { - this.doTranscribeChunk(e.data, emitter, token); - } - }; - return recordingDone.p; }); } - - private async doTranscribeChunk(data: Uint8Array, emitter: Emitter, token: CancellationToken): Promise { - if (token.isCancellationRequested) { - return; - } - - const text = await this.voiceRecognitionService.transcribe(VSBuffer.wrap(data)); - if (token.isCancellationRequested) { - return; - } - - emitter.fire(text); - } } // Register Service diff --git a/src/vs/workbench/test/electron-sandbox/workbenchTestServices.ts b/src/vs/workbench/test/electron-sandbox/workbenchTestServices.ts index 45fa3e437b7..1a40dc62bd5 100644 --- a/src/vs/workbench/test/electron-sandbox/workbenchTestServices.ts +++ b/src/vs/workbench/test/electron-sandbox/workbenchTestServices.ts @@ -51,6 +51,8 @@ export class TestSharedProcessService implements ISharedProcessService { declare readonly _serviceBrand: undefined; + createRawConnection(): never { throw new Error('Not Implemented'); } + getChannel(channelName: string): any { return undefined; } registerChannel(channelName: string, channel: any): void { } diff --git a/src/vs/workbench/workbench.desktop.main.ts b/src/vs/workbench/workbench.desktop.main.ts index b3367ac6ea2..1e429387e2d 100644 --- a/src/vs/workbench/workbench.desktop.main.ts +++ b/src/vs/workbench/workbench.desktop.main.ts @@ -77,7 +77,6 @@ import 'vs/workbench/services/environment/electron-sandbox/shellEnvironmentServi import 'vs/workbench/services/integrity/electron-sandbox/integrityService'; import 'vs/workbench/services/workingCopy/electron-sandbox/workingCopyBackupService'; import 'vs/workbench/services/checksum/electron-sandbox/checksumService'; -import 'vs/workbench/services/voiceRecognition/electron-sandbox/voiceRecognitionService'; import 'vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService'; import 'vs/platform/remote/electron-sandbox/sharedProcessTunnelService'; import 'vs/workbench/services/tunnel/electron-sandbox/tunnelService'; From e36739b66dce75ffbe25711a05c5a4e620a60868 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 17 Aug 2023 12:13:14 +0200 Subject: [PATCH 017/221] voice - some cleanup and :lipstick: --- src/vs/base/common/marshallingIds.ts | 3 +-- src/vs/base/parts/ipc/node/ipc.mp.ts | 4 ++-- .../sharedProcess/contrib/voiceTranscriber.ts | 1 + .../code/node/sharedProcess/sharedProcessMain.ts | 6 +++--- .../sharedProcess/common/sharedProcess.ts | 12 ++++++------ .../sharedProcess/electron-main/sharedProcess.ts | 6 +++--- .../electron-sandbox/sharedProcessService.ts | 8 ++++---- .../electron-sandbox/bufferedVoiceTranscriber.js | 15 +++++++-------- .../workbenchVoiceRecognitionService.ts | 6 +++--- 9 files changed, 30 insertions(+), 31 deletions(-) diff --git a/src/vs/base/common/marshallingIds.ts b/src/vs/base/common/marshallingIds.ts index 7cb27d18f36..abd7698ed92 100644 --- a/src/vs/base/common/marshallingIds.ts +++ b/src/vs/base/common/marshallingIds.ts @@ -20,6 +20,5 @@ export const enum MarshalledId { NotebookCellActionContext, NotebookActionContext, TestItemContext, - Date, - Float32Array + Date } diff --git a/src/vs/base/parts/ipc/node/ipc.mp.ts b/src/vs/base/parts/ipc/node/ipc.mp.ts index 1a8b107dc99..b1648d260d6 100644 --- a/src/vs/base/parts/ipc/node/ipc.mp.ts +++ b/src/vs/base/parts/ipc/node/ipc.mp.ts @@ -43,7 +43,7 @@ export interface IClientConnectionFilter { * @returns `true` if the event was handled * and should not be processed by the server. */ - handled(e: MessageEvent): boolean; + handledClientConnection(e: MessageEvent): boolean; } /** @@ -58,7 +58,7 @@ export class Server extends IPCServer { const onCreateMessageChannel = new Emitter(); process.parentPort.on('message', (e: MessageEvent) => { - if (filter?.handled(e)) { + if (filter?.handledClientConnection(e)) { return; } diff --git a/src/vs/code/node/sharedProcess/contrib/voiceTranscriber.ts b/src/vs/code/node/sharedProcess/contrib/voiceTranscriber.ts index cbd23de96c4..e195f2b8b7a 100644 --- a/src/vs/code/node/sharedProcess/contrib/voiceTranscriber.ts +++ b/src/vs/code/node/sharedProcess/contrib/voiceTranscriber.ts @@ -35,6 +35,7 @@ export class VoiceTranscriber extends Disposable { this._register(toDisposable(() => port.off('message', portHandler))); port.start(); + this._register(toDisposable(() => port.close())); })); } } diff --git a/src/vs/code/node/sharedProcess/sharedProcessMain.ts b/src/vs/code/node/sharedProcess/sharedProcessMain.ts index 91e93fccc59..63b36ab8b0f 100644 --- a/src/vs/code/node/sharedProcess/sharedProcessMain.ts +++ b/src/vs/code/node/sharedProcess/sharedProcessMain.ts @@ -117,7 +117,7 @@ import { NativeEnvironmentService } from 'vs/platform/environment/node/environme import { IVoiceRecognitionService } from 'vs/platform/voiceRecognition/common/voiceRecognitionService'; import { VoiceRecognitionService } from 'vs/platform/voiceRecognition/node/voiceRecognitionService'; import { VoiceTranscriber } from 'vs/code/node/sharedProcess/contrib/voiceTranscriber'; -import { RawSharedProcessConnection, SharedProcessLifecycle } from 'vs/platform/sharedProcess/common/sharedProcess'; +import { SharedProcessRawConnection, SharedProcessLifecycle } from 'vs/platform/sharedProcess/common/sharedProcess'; class SharedProcessMain extends Disposable implements IClientConnectionFilter { @@ -439,14 +439,14 @@ class SharedProcessMain extends Disposable implements IClientConnectionFilter { }); } - handled(e: MessageEvent): boolean { + handledClientConnection(e: MessageEvent): boolean { // This filter on message port messages will look for // attempts of a window to connect raw to the shared // process to handle these connections separate from // our IPC based protocol. - if (e.data !== RawSharedProcessConnection.response) { + if (e.data !== SharedProcessRawConnection.response) { return false; } diff --git a/src/vs/platform/sharedProcess/common/sharedProcess.ts b/src/vs/platform/sharedProcess/common/sharedProcess.ts index 7e443fffb12..5b7e60efc80 100644 --- a/src/vs/platform/sharedProcess/common/sharedProcess.ts +++ b/src/vs/platform/sharedProcess/common/sharedProcess.ts @@ -9,12 +9,12 @@ export const SharedProcessLifecycle = { initDone: 'vscode:shared-process->electron-main=init-done' }; -export const ChannelSharedProcessConnection = { - request: 'vscode:createChannelSharedProcessConnection', - response: 'vscode:createChannelSharedProcessConnectionResult' +export const SharedProcessChannelConnection = { + request: 'vscode:createSharedProcessChannelConnection', + response: 'vscode:createSharedProcessChannelConnectionResult' }; -export const RawSharedProcessConnection = { - request: 'vscode:createRawSharedProcessConnection', - response: 'vscode:createRawSharedProcessConnectionResult' +export const SharedProcessRawConnection = { + request: 'vscode:createSharedProcessRawConnection', + response: 'vscode:createSharedProcessRawConnectionResult' }; diff --git a/src/vs/platform/sharedProcess/electron-main/sharedProcess.ts b/src/vs/platform/sharedProcess/electron-main/sharedProcess.ts index ec41ba8cc7a..c11fa7d0fc5 100644 --- a/src/vs/platform/sharedProcess/electron-main/sharedProcess.ts +++ b/src/vs/platform/sharedProcess/electron-main/sharedProcess.ts @@ -18,7 +18,7 @@ import { UtilityProcess } from 'vs/platform/utilityProcess/electron-main/utility import { NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils'; import { parseSharedProcessDebugPort } from 'vs/platform/environment/node/environmentService'; import { assertIsDefined } from 'vs/base/common/types'; -import { ChannelSharedProcessConnection, RawSharedProcessConnection, SharedProcessLifecycle } from 'vs/platform/sharedProcess/common/sharedProcess'; +import { SharedProcessChannelConnection, SharedProcessRawConnection, SharedProcessLifecycle } from 'vs/platform/sharedProcess/common/sharedProcess'; export class SharedProcess extends Disposable { @@ -43,10 +43,10 @@ export class SharedProcess extends Disposable { private registerListeners(): void { // Shared process channel connections from workbench windows - validatedIpcMain.on(ChannelSharedProcessConnection.request, (e, nonce: string) => this.onWindowConnection(e, nonce, ChannelSharedProcessConnection.response)); + validatedIpcMain.on(SharedProcessChannelConnection.request, (e, nonce: string) => this.onWindowConnection(e, nonce, SharedProcessChannelConnection.response)); // Shared process raw connections from workbench windows - validatedIpcMain.on(RawSharedProcessConnection.request, (e, nonce: string) => this.onWindowConnection(e, nonce, RawSharedProcessConnection.response)); + validatedIpcMain.on(SharedProcessRawConnection.request, (e, nonce: string) => this.onWindowConnection(e, nonce, SharedProcessRawConnection.response)); // Lifecycle this._register(this.lifecycleMainService.onWillShutdown(() => this.onWillShutdown())); diff --git a/src/vs/workbench/services/sharedProcess/electron-sandbox/sharedProcessService.ts b/src/vs/workbench/services/sharedProcess/electron-sandbox/sharedProcessService.ts index 11a2fd6a72b..fffa5df2feb 100644 --- a/src/vs/workbench/services/sharedProcess/electron-sandbox/sharedProcessService.ts +++ b/src/vs/workbench/services/sharedProcess/electron-sandbox/sharedProcessService.ts @@ -8,7 +8,7 @@ import { IChannel, IServerChannel, getDelayedChannel } from 'vs/base/parts/ipc/c import { ILogService } from 'vs/platform/log/common/log'; import { Disposable } from 'vs/base/common/lifecycle'; import { ISharedProcessService } from 'vs/platform/ipc/electron-sandbox/services'; -import { ChannelSharedProcessConnection, RawSharedProcessConnection } from 'vs/platform/sharedProcess/common/sharedProcess'; +import { SharedProcessChannelConnection, SharedProcessRawConnection } from 'vs/platform/sharedProcess/common/sharedProcess'; import { mark } from 'vs/base/common/performance'; import { Barrier, timeout } from 'vs/base/common/async'; import { acquirePort } from 'vs/base/parts/ipc/electron-sandbox/ipc.mp'; @@ -45,7 +45,7 @@ export class SharedProcessService extends Disposable implements ISharedProcessSe // Acquire a message port connected to the shared process mark('code/willConnectSharedProcess'); this.logService.trace('Renderer->SharedProcess#connect: before acquirePort'); - const port = await acquirePort(ChannelSharedProcessConnection.request, ChannelSharedProcessConnection.response); + const port = await acquirePort(SharedProcessChannelConnection.request, SharedProcessChannelConnection.response); mark('code/didConnectSharedProcess'); this.logService.trace('Renderer->SharedProcess#connect: connection established'); @@ -69,11 +69,11 @@ export class SharedProcessService extends Disposable implements ISharedProcessSe async createRawConnection(): Promise { // Await initialization of the shared process - await this.connect(); + await this.withSharedProcessConnection; // Create a new port to the shared process this.logService.trace('Renderer->SharedProcess#createRawConnection: before acquirePort'); - const port = await acquirePort(RawSharedProcessConnection.request, RawSharedProcessConnection.response); + const port = await acquirePort(SharedProcessRawConnection.request, SharedProcessRawConnection.response); this.logService.trace('Renderer->SharedProcess#createRawConnection: connection established'); return port; diff --git a/src/vs/workbench/services/voiceRecognition/electron-sandbox/bufferedVoiceTranscriber.js b/src/vs/workbench/services/voiceRecognition/electron-sandbox/bufferedVoiceTranscriber.js index 3e4d6641c22..7b99644fa3c 100644 --- a/src/vs/workbench/services/voiceRecognition/electron-sandbox/bufferedVoiceTranscriber.js +++ b/src/vs/workbench/services/voiceRecognition/electron-sandbox/bufferedVoiceTranscriber.js @@ -13,7 +13,7 @@ class BufferedVoiceTranscriber extends AudioWorkletProcessor { super(); this.channelCount = 1; - this.bufferTimespan = 4000; + this.bufferTimespan = 2000; this.startTime = undefined; this.allInputFloat32Array = undefined; @@ -27,16 +27,16 @@ class BufferedVoiceTranscriber extends AudioWorkletProcessor { // @ts-ignore const port = this.port; port.onmessage = event => { - if (event.data === 'vscode:transferPortToAudioWorklet') { - this.sharedProcessPort = event.ports[0]; + if (event.data === 'vscode:transferSharedProcessConnection') { + this.sharedProcessConnection = event.ports[0]; - this.sharedProcessPort.onmessage = event => { + this.sharedProcessConnection.onmessage = event => { if (typeof event.data === 'string') { port.postMessage(event.data); } }; - this.sharedProcessPort.start(); + this.sharedProcessConnection.start(); } }; } @@ -56,14 +56,13 @@ class BufferedVoiceTranscriber extends AudioWorkletProcessor { this.currentInputFloat32Arrays.push(inputChannelData.slice(0)); - if (Date.now() - this.startTime > this.bufferTimespan && this.sharedProcessPort) { + if (Date.now() - this.startTime > this.bufferTimespan && this.sharedProcessConnection) { const currentInputFloat32Arrays = this.currentInputFloat32Arrays; this.currentInputFloat32Arrays = []; this.allInputFloat32Array = this.joinFloat32Arrays(this.allInputFloat32Array ? [this.allInputFloat32Array, ...currentInputFloat32Arrays] : currentInputFloat32Arrays); - // @ts-ignore - this.sharedProcessPort.postMessage(this.allInputFloat32Array); + this.sharedProcessConnection.postMessage(this.allInputFloat32Array); this.startTime = Date.now(); } diff --git a/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts b/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts index 523b07d1066..4ccbde62b10 100644 --- a/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts +++ b/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts @@ -50,10 +50,10 @@ class BufferedVoiceTranscriber extends AudioWorkletNode { } async start(token: CancellationToken): Promise { - const rawSharedProcessConnection = await this.sharedProcessService.createRawConnection(); - token.onCancellationRequested(() => rawSharedProcessConnection.close()); + const sharedProcessConnection = await this.sharedProcessService.createRawConnection(); + token.onCancellationRequested(() => sharedProcessConnection.close()); - this.port.postMessage('vscode:transferPortToAudioWorklet', [rawSharedProcessConnection]); + this.port.postMessage('vscode:transferSharedProcessConnection', [sharedProcessConnection]); } } From ace7ce5f52efb90ced1d94d263f84178834f1ff8 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 17 Aug 2023 12:32:33 +0200 Subject: [PATCH 018/221] voice - convert audio worklet to typescript --- ...scriber.js => bufferedVoiceTranscriber.ts} | 49 +++++++++---------- .../workbenchVoiceRecognitionService.ts | 1 - 2 files changed, 22 insertions(+), 28 deletions(-) rename src/vs/workbench/services/voiceRecognition/electron-sandbox/{bufferedVoiceTranscriber.js => bufferedVoiceTranscriber.ts} (68%) diff --git a/src/vs/workbench/services/voiceRecognition/electron-sandbox/bufferedVoiceTranscriber.js b/src/vs/workbench/services/voiceRecognition/electron-sandbox/bufferedVoiceTranscriber.ts similarity index 68% rename from src/vs/workbench/services/voiceRecognition/electron-sandbox/bufferedVoiceTranscriber.js rename to src/vs/workbench/services/voiceRecognition/electron-sandbox/bufferedVoiceTranscriber.ts index 7b99644fa3c..bb6c8eaaa17 100644 --- a/src/vs/workbench/services/voiceRecognition/electron-sandbox/bufferedVoiceTranscriber.js +++ b/src/vs/workbench/services/voiceRecognition/electron-sandbox/bufferedVoiceTranscriber.ts @@ -3,36 +3,38 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -//@ts-check -'use strict'; +declare class AudioWorkletProcessor { + + readonly port: MessagePort; + + process(inputs: [Float32Array[]], outputs: [Float32Array[]]): boolean; +} -// @ts-ignore class BufferedVoiceTranscriber extends AudioWorkletProcessor { + private static readonly BUFFER_TIMESPAN = 2000; + + private startTime: number | undefined = undefined; + + private allInputFloat32Array: Float32Array | undefined = undefined; + private currentInputFloat32Arrays: Float32Array[] = []; + + private sharedProcessConnection: MessagePort | undefined = undefined; + constructor() { super(); - this.channelCount = 1; - this.bufferTimespan = 2000; - this.startTime = undefined; - - this.allInputFloat32Array = undefined; - this.currentInputFloat32Arrays = []; // buffer over the duration of bufferTimespan - this.registerListeners(); } - registerListeners() { - - // @ts-ignore - const port = this.port; - port.onmessage = event => { + private registerListeners() { + this.port.onmessage = event => { if (event.data === 'vscode:transferSharedProcessConnection') { this.sharedProcessConnection = event.ports[0]; this.sharedProcessConnection.onmessage = event => { if (typeof event.data === 'string') { - port.postMessage(event.data); + this.port.postMessage(event.data); } }; @@ -41,22 +43,19 @@ class BufferedVoiceTranscriber extends AudioWorkletProcessor { }; } - /** - * @param {[[Float32Array]]} inputs - */ - process(inputs) { + override process(inputs: [Float32Array[]]): boolean { if (this.startTime === undefined) { this.startTime = Date.now(); } const inputChannelData = inputs[0][0]; if ((!(inputChannelData instanceof Float32Array))) { - return; + return true; } this.currentInputFloat32Arrays.push(inputChannelData.slice(0)); - if (Date.now() - this.startTime > this.bufferTimespan && this.sharedProcessConnection) { + if (Date.now() - this.startTime > BufferedVoiceTranscriber.BUFFER_TIMESPAN && this.sharedProcessConnection) { const currentInputFloat32Arrays = this.currentInputFloat32Arrays; this.currentInputFloat32Arrays = []; @@ -70,11 +69,7 @@ class BufferedVoiceTranscriber extends AudioWorkletProcessor { return true; } - /** - * @param {Float32Array[]} float32Arrays - * @returns {Float32Array} - */ - joinFloat32Arrays(float32Arrays) { + private joinFloat32Arrays(float32Arrays: Float32Array[]): Float32Array { const result = new Float32Array(float32Arrays.reduce((acc, curr) => acc + curr.length, 0)); let offset = 0; diff --git a/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts b/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts index 4ccbde62b10..329b340651b 100644 --- a/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts +++ b/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts @@ -62,7 +62,6 @@ class BufferedVoiceTranscriber extends AudioWorkletNode { // - how to make this a singleton service that enables ref-counting on multiple callers? // - cancellation should flow to the shared process // - voice module should directly transcribe the PCM32 data without wav+file conversion -// - the audio worklet should be a TS file (try without any import/export?) export class WorkbenchVoiceRecognitionService implements IWorkbenchVoiceRecognitionService { From 614bfb3d3352f7b848df98d68af95797063577fc Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Thu, 17 Aug 2023 14:07:03 +0200 Subject: [PATCH 019/221] sending diagnostics on file open --- .../src/languageFeatures/diagnostics.ts | 50 +++++++++---------- .../src/typescriptServiceClient.ts | 4 ++ 2 files changed, 29 insertions(+), 25 deletions(-) diff --git a/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts b/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts index 5981e63ea6e..515ee7889fb 100644 --- a/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts +++ b/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts @@ -154,7 +154,6 @@ export class DiagnosticsManager extends Disposable { private readonly _settings = new DiagnosticSettings(); private readonly _currentDiagnostics: vscode.DiagnosticCollection; private readonly _pendingUpdates: ResourceMap; - private readonly _telemetryReporter: TelemetryReporter; private readonly _updateDelay = 50; @@ -168,7 +167,30 @@ export class DiagnosticsManager extends Disposable { this._pendingUpdates = new ResourceMap(undefined, { onCaseInsensitiveFileSystem }); this._currentDiagnostics = this._register(vscode.languages.createDiagnosticCollection(owner)); - this._telemetryReporter = telemetryReporter; + this._register(vscode.workspace.onDidOpenTextDocument((document) => { + const diagnostics = this.getDiagnostics(document.uri); + const diagnoticCodes = diagnostics.reduce(function (result: number[], d: vscode.Diagnostic) { + const code = d.code; + if (typeof code === 'string' || typeof code === 'number') { + result.push(Number(code)); + } else if (code !== undefined) { + result.push(Number(code.value)); + } + return result; + }, []).sort(); + /* __GDPR__ + "typescript.diagnostics" : { + "owner": "@aiday-mar", + "diagnosticCodes" : { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" }, + "${include}": [ + "${TypeScriptCommonProperties}" + ] + } + */ + telemetryReporter.logTelemetry('typescript.diagnostics', { + diagnoticCodes: diagnoticCodes.join(', ') + }); + })); } public override dispose() { @@ -242,29 +264,7 @@ export class DiagnosticsManager extends Disposable { } public getDiagnostics(file: vscode.Uri): ReadonlyArray { - const diagnostics = this._currentDiagnostics.get(file) || []; - const diagnoticCodes = diagnostics.reduce(function (result: number[], d: vscode.Diagnostic) { - const code = d.code; - if (typeof code === 'string' || typeof code === 'number') { - result.push(Number(code)); - } else if (code !== undefined) { - result.push(Number(code.value)); - } - return result; - }, []).sort(); - /* __GDPR__ - "typescript.diagnostics" : { - "owner": "@aiday-mar", - "diagnosticCodes" : { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" }, - "${include}": [ - "${TypeScriptCommonProperties}" - ] - } - */ - this._telemetryReporter.logTelemetry('typescript.diagnostics', { - diagnoticCodes: diagnoticCodes.join(', ') - }); - return diagnostics; + return this._currentDiagnostics.get(file) || []; } private scheduleDiagnosticsUpdate(file: vscode.Uri) { diff --git a/extensions/typescript-language-features/src/typescriptServiceClient.ts b/extensions/typescript-language-features/src/typescriptServiceClient.ts index c165f82db40..e9e303e5b4f 100644 --- a/extensions/typescript-language-features/src/typescriptServiceClient.ts +++ b/extensions/typescript-language-features/src/typescriptServiceClient.ts @@ -468,6 +468,9 @@ export default class TypeScriptServiceClient extends Disposable implements IType } this.serviceExited(!this.isRestarting); this.isRestarting = false; + + // TODO: on handle exit, we need to send the typescript errors that we have accumulated + console.log('on handle exit'); }); handle.onEvent(event => this.dispatchEvent(event)); @@ -579,6 +582,7 @@ export default class TypeScriptServiceClient extends Disposable implements IType }; } + // TODO: service exited will close the client service, is this the one that we need to monitor? private serviceExited(restart: boolean): void { this.loadingIndicator.reset(); From ce752f607aa2cd3912e2daac7d554fcb35e6752e Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 17 Aug 2023 14:10:01 +0200 Subject: [PATCH 020/221] voice - better ports lifecycle --- build/gulpfile.vscode.js | 2 +- .../sharedProcess/contrib/voiceTranscriber.ts | 16 ++++++- .../common/voiceRecognitionService.ts | 3 +- .../node/voiceRecognitionService.ts | 6 +-- ...criber.ts => voiceTranscriptionWorklet.ts} | 44 +++++++++++++------ .../workbenchVoiceRecognitionService.ts | 38 +++++++++++----- 6 files changed, 78 insertions(+), 31 deletions(-) rename src/vs/workbench/services/voiceRecognition/electron-sandbox/{bufferedVoiceTranscriber.ts => voiceTranscriptionWorklet.ts} (68%) diff --git a/build/gulpfile.vscode.js b/build/gulpfile.vscode.js index cd0a762dfa7..5f7f5ce4470 100644 --- a/build/gulpfile.vscode.js +++ b/build/gulpfile.vscode.js @@ -72,7 +72,7 @@ const vscodeResources = [ 'out-build/vs/workbench/contrib/terminal/browser/media/*.sh', 'out-build/vs/workbench/contrib/terminal/browser/media/*.zsh', 'out-build/vs/workbench/contrib/webview/browser/pre/*.js', - 'out-build/vs/workbench/services/voiceRecognition/electron-sandbox/bufferedVoiceTranscriber.js', + 'out-build/vs/workbench/services/voiceRecognition/electron-sandbox/voiceTranscriptionWorklet.js', 'out-build/vs/**/markdown.css', 'out-build/vs/workbench/contrib/tasks/**/*.json', '!**/test/**' diff --git a/src/vs/code/node/sharedProcess/contrib/voiceTranscriber.ts b/src/vs/code/node/sharedProcess/contrib/voiceTranscriber.ts index e195f2b8b7a..48a7843730a 100644 --- a/src/vs/code/node/sharedProcess/contrib/voiceTranscriber.ts +++ b/src/vs/code/node/sharedProcess/contrib/voiceTranscriber.ts @@ -7,12 +7,15 @@ import { Event } from 'vs/base/common/event'; import { MessagePortMain, MessageEvent } from 'vs/base/parts/sandbox/node/electronTypes'; import { Disposable, toDisposable } from 'vs/base/common/lifecycle'; import { IVoiceRecognitionService } from 'vs/platform/voiceRecognition/common/voiceRecognitionService'; +import { ILogService } from 'vs/platform/log/common/log'; +import { CancellationTokenSource } from 'vs/base/common/cancellation'; export class VoiceTranscriber extends Disposable { constructor( private readonly onDidWindowConnectRaw: Event, @IVoiceRecognitionService private readonly voiceRecognitionService: IVoiceRecognitionService, + @ILogService private readonly logService: ILogService ) { super(); @@ -21,12 +24,17 @@ export class VoiceTranscriber extends Disposable { private registerListeners(): void { this._register(this.onDidWindowConnectRaw(port => { + this.logService.info(`[voice] transcriber: new connection`); + + const cts = new CancellationTokenSource(); + this._register(toDisposable(() => cts.dispose(true))); + const portHandler = async (e: MessageEvent) => { if (!(e.data instanceof Float32Array)) { return; } - const result = await this.voiceRecognitionService.transcribe(e.data); + const result = await this.voiceRecognitionService.transcribe(e.data, cts.token); port.postMessage(result); }; @@ -36,6 +44,12 @@ export class VoiceTranscriber extends Disposable { port.start(); this._register(toDisposable(() => port.close())); + + port.on('close', () => { + this.logService.info(`[voice] transcriber: closed connection`); + + cts.dispose(true); + }); })); } } diff --git a/src/vs/platform/voiceRecognition/common/voiceRecognitionService.ts b/src/vs/platform/voiceRecognition/common/voiceRecognitionService.ts index a563a2e45cd..ca52963092f 100644 --- a/src/vs/platform/voiceRecognition/common/voiceRecognitionService.ts +++ b/src/vs/platform/voiceRecognition/common/voiceRecognitionService.ts @@ -3,6 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { CancellationToken } from 'vs/base/common/cancellation'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; export const IVoiceRecognitionService = createDecorator('voiceRecognitionService'); @@ -21,5 +22,5 @@ export interface IVoiceRecognitionService { * - 16khz sampling rate * - 16bit sample size */ - transcribe(channelData: Float32Array): Promise; + transcribe(channelData: Float32Array, cancellation: CancellationToken): Promise; } diff --git a/src/vs/platform/voiceRecognition/node/voiceRecognitionService.ts b/src/vs/platform/voiceRecognition/node/voiceRecognitionService.ts index a67fb2c54b4..f1e259b76ad 100644 --- a/src/vs/platform/voiceRecognition/node/voiceRecognitionService.ts +++ b/src/vs/platform/voiceRecognition/node/voiceRecognitionService.ts @@ -3,6 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { CancellationToken } from 'vs/base/common/cancellation'; import { ILogService } from 'vs/platform/log/common/log'; import { IVoiceRecognitionService } from 'vs/platform/voiceRecognition/common/voiceRecognitionService'; @@ -14,7 +15,7 @@ export class VoiceRecognitionService implements IVoiceRecognitionService { @ILogService private readonly logService: ILogService ) { } - async transcribe(channelData: Float32Array): Promise { + async transcribe(channelData: Float32Array, cancellation: CancellationToken): Promise { this.logService.info(`[voice] transcribe(${channelData.length}): Begin`); const modulePath = process.env.VSCODE_VOICE_MODULE_PATH; @@ -23,7 +24,6 @@ export class VoiceRecognitionService implements IVoiceRecognitionService { } const now = Date.now(); - const conversionTime = Date.now() - now; const voiceModule: { transcribe: (audioBuffer: { channelCount: 1; sampleRate: 16000; sampleSize: 16; channelData: Float32Array }, options: { language: string | 'auto'; suppressNonSpeechTokens: boolean }) => Promise } = require.__$__nodeRequire(modulePath); @@ -37,7 +37,7 @@ export class VoiceRecognitionService implements IVoiceRecognitionService { suppressNonSpeechTokens: true }); - this.logService.info(`[voice] transcribe(${channelData.length}): End (text: "${text}", took: ${Date.now() - now}ms total, ${conversionTime}ms uint8->float32 conversion)`); + this.logService.info(`[voice] transcribe(${channelData.length}): End (text: "${text}", took: ${Date.now() - now}ms)`); return text; } diff --git a/src/vs/workbench/services/voiceRecognition/electron-sandbox/bufferedVoiceTranscriber.ts b/src/vs/workbench/services/voiceRecognition/electron-sandbox/voiceTranscriptionWorklet.ts similarity index 68% rename from src/vs/workbench/services/voiceRecognition/electron-sandbox/bufferedVoiceTranscriber.ts rename to src/vs/workbench/services/voiceRecognition/electron-sandbox/voiceTranscriptionWorklet.ts index bb6c8eaaa17..d6edf688d1f 100644 --- a/src/vs/workbench/services/voiceRecognition/electron-sandbox/bufferedVoiceTranscriber.ts +++ b/src/vs/workbench/services/voiceRecognition/electron-sandbox/voiceTranscriptionWorklet.ts @@ -10,7 +10,7 @@ declare class AudioWorkletProcessor { process(inputs: [Float32Array[]], outputs: [Float32Array[]]): boolean; } -class BufferedVoiceTranscriber extends AudioWorkletProcessor { +class VoiceTranscriptionWorklet extends AudioWorkletProcessor { private static readonly BUFFER_TIMESPAN = 2000; @@ -21,6 +21,8 @@ class BufferedVoiceTranscriber extends AudioWorkletProcessor { private sharedProcessConnection: MessagePort | undefined = undefined; + private stopped: boolean = false; + constructor() { super(); @@ -29,16 +31,32 @@ class BufferedVoiceTranscriber extends AudioWorkletProcessor { private registerListeners() { this.port.onmessage = event => { - if (event.data === 'vscode:transferSharedProcessConnection') { - this.sharedProcessConnection = event.ports[0]; + switch (event.data) { + case 'vscode:startVoiceTranscription': { + this.sharedProcessConnection = event.ports[0]; - this.sharedProcessConnection.onmessage = event => { - if (typeof event.data === 'string') { - this.port.postMessage(event.data); - } - }; + this.sharedProcessConnection.onmessage = event => { + if (this.stopped) { + return; + } - this.sharedProcessConnection.start(); + if (typeof event.data === 'string') { + this.port.postMessage(event.data); + } + }; + + this.sharedProcessConnection.start(); + break; + } + + case 'vscode:stopVoiceTranscription': { + this.stopped = true; + + this.sharedProcessConnection?.close(); + this.sharedProcessConnection = undefined; + + break; + } } }; } @@ -50,12 +68,12 @@ class BufferedVoiceTranscriber extends AudioWorkletProcessor { const inputChannelData = inputs[0][0]; if ((!(inputChannelData instanceof Float32Array))) { - return true; + return !this.stopped; } this.currentInputFloat32Arrays.push(inputChannelData.slice(0)); - if (Date.now() - this.startTime > BufferedVoiceTranscriber.BUFFER_TIMESPAN && this.sharedProcessConnection) { + if (Date.now() - this.startTime > VoiceTranscriptionWorklet.BUFFER_TIMESPAN && this.sharedProcessConnection) { const currentInputFloat32Arrays = this.currentInputFloat32Arrays; this.currentInputFloat32Arrays = []; @@ -66,7 +84,7 @@ class BufferedVoiceTranscriber extends AudioWorkletProcessor { this.startTime = Date.now(); } - return true; + return !this.stopped; } private joinFloat32Arrays(float32Arrays: Float32Array[]): Float32Array { @@ -83,4 +101,4 @@ class BufferedVoiceTranscriber extends AudioWorkletProcessor { } // @ts-ignore -registerProcessor('buffered-voice-transcriber', BufferedVoiceTranscriber); +registerProcessor('voice-transcription-worklet', VoiceTranscriptionWorklet); diff --git a/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts b/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts index 329b340651b..a676ed1aff5 100644 --- a/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts +++ b/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts @@ -28,7 +28,7 @@ export interface IWorkbenchVoiceRecognitionService { transcribe(cancellation: CancellationToken): Event; } -class BufferedVoiceTranscriber extends AudioWorkletNode { +class VoiceTranscriptionWorkletNode extends AudioWorkletNode { constructor( context: BaseAudioContext, @@ -36,7 +36,7 @@ class BufferedVoiceTranscriber extends AudioWorkletNode { private readonly onDidTranscribe: Emitter, private readonly sharedProcessService: ISharedProcessService ) { - super(context, 'buffered-voice-transcriber', options); + super(context, 'voice-transcription-worklet', options); this.registerListeners(); } @@ -51,16 +51,19 @@ class BufferedVoiceTranscriber extends AudioWorkletNode { async start(token: CancellationToken): Promise { const sharedProcessConnection = await this.sharedProcessService.createRawConnection(); - token.onCancellationRequested(() => sharedProcessConnection.close()); - this.port.postMessage('vscode:transferSharedProcessConnection', [sharedProcessConnection]); + token.onCancellationRequested(() => { + this.port.postMessage('vscode:stopVoiceTranscription'); + this.disconnect(); + }); + + this.port.postMessage('vscode:startVoiceTranscription', [sharedProcessConnection]); } } // TODO@voice // - how to prevent data processing accumulation when processing is slow? // - how to make this a singleton service that enables ref-counting on multiple callers? -// - cancellation should flow to the shared process // - voice module should directly transcribe the PCM32 data without wav+file conversion export class WorkbenchVoiceRecognitionService implements IWorkbenchVoiceRecognitionService { @@ -85,8 +88,8 @@ export class WorkbenchVoiceRecognitionService implements IWorkbenchVoiceRecognit return onDidTranscribe.event; } - private async doTranscribe(onDidTranscribe: Emitter, token: CancellationToken): Promise { - return this.progressService.withProgress({ + private doTranscribe(onDidTranscribe: Emitter, token: CancellationToken): void { + this.progressService.withProgress({ location: ProgressLocation.Window, title: localize('voiceTranscription', "Voice Transcription"), }, async progress => { @@ -116,21 +119,32 @@ export class WorkbenchVoiceRecognitionService implements IWorkbenchVoiceRecognit const microphoneSource = audioContext.createMediaStreamSource(microphoneDevice); token.onCancellationRequested(() => { - microphoneDevice.getTracks().forEach(track => track.stop()); + for (const track of microphoneDevice.getTracks()) { + track.stop(); + } + microphoneSource.disconnect(); audioContext.close(); recordingDone.complete(); }); - await audioContext.audioWorklet.addModule(FileAccess.asBrowserUri('vs/workbench/services/voiceRecognition/electron-sandbox/bufferedVoiceTranscriber.js').toString(true)); + await audioContext.audioWorklet.addModule(FileAccess.asBrowserUri('vs/workbench/services/voiceRecognition/electron-sandbox/voiceTranscriptionWorklet.js').toString(true)); - const bufferedVoiceTranscriberTarget = new BufferedVoiceTranscriber(audioContext, { + if (token.isCancellationRequested) { + return; + } + + const voiceTranscriptionTarget = new VoiceTranscriptionWorkletNode(audioContext, { channelCount: WorkbenchVoiceRecognitionService.AUDIO_CHANNELS, channelCountMode: 'explicit' }, onDidTranscribe, this.sharedProcessService); - await bufferedVoiceTranscriberTarget.start(token); + await voiceTranscriptionTarget.start(token); - microphoneSource.connect(bufferedVoiceTranscriberTarget); + if (token.isCancellationRequested) { + return; + } + + microphoneSource.connect(voiceTranscriptionTarget); progress.report({ message: localize('voiceTranscriptionRecording', "Recording from microphone...") }); From 0d4db5ffc407ffab5058dc5ea7de1dc511a5d150 Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Thu, 17 Aug 2023 14:35:27 +0200 Subject: [PATCH 021/221] sending the diagnostics on handle exit --- .../src/languageFeatures/diagnostics.ts | 50 +++++++++++++------ .../src/typescriptServiceClient.ts | 6 +-- 2 files changed, 37 insertions(+), 19 deletions(-) diff --git a/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts b/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts index 515ee7889fb..8a4a0c79e95 100644 --- a/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts +++ b/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts @@ -149,12 +149,40 @@ class DiagnosticSettings { } } +class DiagnosticsTelemetryManager { + + private _diagnosticCodes: number[] = []; + + constructor(private readonly _telemetryReporter: TelemetryReporter) { } + + public addDiagnosticCodes(codes: number[]) { + this._diagnosticCodes.push(...codes); + this._diagnosticCodes.sort(); + } + + public sendDiagnosticsCodesTelemetry(): void { + /* __GDPR__ + "typescript.diagnostics" : { + "owner": "@aiday-mar", + "diagnosticCodes" : { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" }, + "${include}": [ + "${TypeScriptCommonProperties}" + ] + } + */ + this._telemetryReporter.logTelemetry('typescript.diagnostics', { + diagnoticCodes: this._diagnosticCodes.join(', ') + }); + this._diagnosticCodes = []; + } +} + export class DiagnosticsManager extends Disposable { private readonly _diagnostics: ResourceMap; private readonly _settings = new DiagnosticSettings(); private readonly _currentDiagnostics: vscode.DiagnosticCollection; private readonly _pendingUpdates: ResourceMap; - + private readonly _diagnosticsTelemetryManager: DiagnosticsTelemetryManager; private readonly _updateDelay = 50; constructor( @@ -167,6 +195,7 @@ export class DiagnosticsManager extends Disposable { this._pendingUpdates = new ResourceMap(undefined, { onCaseInsensitiveFileSystem }); this._currentDiagnostics = this._register(vscode.languages.createDiagnosticCollection(owner)); + this._diagnosticsTelemetryManager = new DiagnosticsTelemetryManager(telemetryReporter); this._register(vscode.workspace.onDidOpenTextDocument((document) => { const diagnostics = this.getDiagnostics(document.uri); const diagnoticCodes = diagnostics.reduce(function (result: number[], d: vscode.Diagnostic) { @@ -177,22 +206,15 @@ export class DiagnosticsManager extends Disposable { result.push(Number(code.value)); } return result; - }, []).sort(); - /* __GDPR__ - "typescript.diagnostics" : { - "owner": "@aiday-mar", - "diagnosticCodes" : { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" }, - "${include}": [ - "${TypeScriptCommonProperties}" - ] - } - */ - telemetryReporter.logTelemetry('typescript.diagnostics', { - diagnoticCodes: diagnoticCodes.join(', ') - }); + }, []); + this._diagnosticsTelemetryManager.addDiagnosticCodes(diagnoticCodes); })); } + public sendDiagnosticsCodesTelemetry(): void { + this._diagnosticsTelemetryManager.sendDiagnosticsCodesTelemetry(); + } + public override dispose() { super.dispose(); diff --git a/extensions/typescript-language-features/src/typescriptServiceClient.ts b/extensions/typescript-language-features/src/typescriptServiceClient.ts index e9e303e5b4f..d04f41e4142 100644 --- a/extensions/typescript-language-features/src/typescriptServiceClient.ts +++ b/extensions/typescript-language-features/src/typescriptServiceClient.ts @@ -456,7 +456,7 @@ export default class TypeScriptServiceClient extends Disposable implements IType } */ this.logTelemetry('tsserver.exitWithCode', { code: code ?? undefined, signal: signal ?? undefined }); - + this.diagnosticsManager.sendDiagnosticsCodesTelemetry(); if (this.token !== mytoken) { // this is coming from an old process @@ -468,9 +468,6 @@ export default class TypeScriptServiceClient extends Disposable implements IType } this.serviceExited(!this.isRestarting); this.isRestarting = false; - - // TODO: on handle exit, we need to send the typescript errors that we have accumulated - console.log('on handle exit'); }); handle.onEvent(event => this.dispatchEvent(event)); @@ -582,7 +579,6 @@ export default class TypeScriptServiceClient extends Disposable implements IType }; } - // TODO: service exited will close the client service, is this the one that we need to monitor? private serviceExited(restart: boolean): void { this.loadingIndicator.reset(); From 733530d9e5842337c011915e1259d5c1b1f6387a Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 17 Aug 2023 14:36:19 +0200 Subject: [PATCH 022/221] voice - implement sequential transcriptions --- src/vs/base/common/async.ts | 6 +- .../sharedProcess/contrib/voiceTranscriber.ts | 98 +++++++++++++------ .../node/sharedProcess/sharedProcessMain.ts | 4 +- 3 files changed, 73 insertions(+), 35 deletions(-) diff --git a/src/vs/base/common/async.ts b/src/vs/base/common/async.ts index e00f3d59653..6b87b06b21a 100644 --- a/src/vs/base/common/async.ts +++ b/src/vs/base/common/async.ts @@ -1294,12 +1294,8 @@ export class TaskSequentializer { private _next?: INextTask; hasPending(taskId?: number): this is ITaskSequentializerWithPendingTask { - if (!this._pending) { - return false; - } - if (typeof taskId === 'number') { - return this._pending.taskId === taskId; + return this._pending?.taskId === taskId; } return !!this._pending; diff --git a/src/vs/code/node/sharedProcess/contrib/voiceTranscriber.ts b/src/vs/code/node/sharedProcess/contrib/voiceTranscriber.ts index 48a7843730a..6b8f8bf3084 100644 --- a/src/vs/code/node/sharedProcess/contrib/voiceTranscriber.ts +++ b/src/vs/code/node/sharedProcess/contrib/voiceTranscriber.ts @@ -8,9 +8,10 @@ import { MessagePortMain, MessageEvent } from 'vs/base/parts/sandbox/node/electr import { Disposable, toDisposable } from 'vs/base/common/lifecycle'; import { IVoiceRecognitionService } from 'vs/platform/voiceRecognition/common/voiceRecognitionService'; import { ILogService } from 'vs/platform/log/common/log'; -import { CancellationTokenSource } from 'vs/base/common/cancellation'; +import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation'; +import { TaskSequentializer } from 'vs/base/common/async'; -export class VoiceTranscriber extends Disposable { +export class VoiceTranscriptionManager extends Disposable { constructor( private readonly onDidWindowConnectRaw: Event, @@ -24,32 +25,73 @@ export class VoiceTranscriber extends Disposable { private registerListeners(): void { this._register(this.onDidWindowConnectRaw(port => { - this.logService.info(`[voice] transcriber: new connection`); - - const cts = new CancellationTokenSource(); - this._register(toDisposable(() => cts.dispose(true))); - - const portHandler = async (e: MessageEvent) => { - if (!(e.data instanceof Float32Array)) { - return; - } - - const result = await this.voiceRecognitionService.transcribe(e.data, cts.token); - - port.postMessage(result); - }; - - port.on('message', portHandler); - this._register(toDisposable(() => port.off('message', portHandler))); - - port.start(); - this._register(toDisposable(() => port.close())); - - port.on('close', () => { - this.logService.info(`[voice] transcriber: closed connection`); - - cts.dispose(true); - }); + this._register(new VoiceTranscriber(port, this.voiceRecognitionService, this.logService)); })); } } + +class VoiceTranscriber extends Disposable { + + private readonly transcriptionSequentializer = new TaskSequentializer(); + + private requests = 0; + + constructor( + private readonly port: MessagePortMain, + private readonly voiceRecognitionService: IVoiceRecognitionService, + private readonly logService: ILogService + ) { + super(); + + this.registerListeners(); + } + + private registerListeners(): void { + this.logService.info(`[voice] transcriber: new connection`); + + const cts = new CancellationTokenSource(); + this._register(toDisposable(() => cts.dispose(true))); + + const requestHandler = (e: MessageEvent) => this.handleRequest(e, cts.token); + this.port.on('message', requestHandler); + this._register(toDisposable(() => this.port.off('message', requestHandler))); + + this.port.start(); + this._register(toDisposable(() => this.port.close())); + + this.port.on('close', () => { + this.logService.info(`[voice] transcriber: closed connection`); + + cts.dispose(true); + this.transcriptionSequentializer.cancelPending(); + }); + } + + private async handleRequest(e: MessageEvent, cancellation: CancellationToken): Promise { + if (!(e.data instanceof Float32Array)) { + return; + } + + this.requests++; + + if (!this.transcriptionSequentializer.hasPending()) { + this.transcriptionSequentializer.setPending(this.requests, this.transcribe(e.data, cancellation)); + } else { + this.transcriptionSequentializer.setNext(() => this.transcribe(e.data, cancellation)); + } + } + + private async transcribe(channelData: Float32Array, cancellation: CancellationToken): Promise { + if (cancellation.isCancellationRequested) { + return; + } + + const result = await this.voiceRecognitionService.transcribe(channelData, cancellation); + + if (cancellation.isCancellationRequested) { + return; + } + + this.port.postMessage(result); + } +} diff --git a/src/vs/code/node/sharedProcess/sharedProcessMain.ts b/src/vs/code/node/sharedProcess/sharedProcessMain.ts index 63b36ab8b0f..bf30c403b93 100644 --- a/src/vs/code/node/sharedProcess/sharedProcessMain.ts +++ b/src/vs/code/node/sharedProcess/sharedProcessMain.ts @@ -116,7 +116,7 @@ import { nodeSocketFactory } from 'vs/platform/remote/node/nodeSocketFactory'; import { NativeEnvironmentService } from 'vs/platform/environment/node/environmentService'; import { IVoiceRecognitionService } from 'vs/platform/voiceRecognition/common/voiceRecognitionService'; import { VoiceRecognitionService } from 'vs/platform/voiceRecognition/node/voiceRecognitionService'; -import { VoiceTranscriber } from 'vs/code/node/sharedProcess/contrib/voiceTranscriber'; +import { VoiceTranscriptionManager } from 'vs/code/node/sharedProcess/contrib/voiceTranscriber'; import { SharedProcessRawConnection, SharedProcessLifecycle } from 'vs/platform/sharedProcess/common/sharedProcess'; class SharedProcessMain extends Disposable implements IClientConnectionFilter { @@ -179,7 +179,7 @@ class SharedProcessMain extends Disposable implements IClientConnectionFilter { instantiationService.createInstance(LocalizationsUpdater), instantiationService.createInstance(ExtensionsContributions), instantiationService.createInstance(UserDataProfilesCleaner), - instantiationService.createInstance(VoiceTranscriber, this.onDidWindowConnectRaw.event) + instantiationService.createInstance(VoiceTranscriptionManager, this.onDidWindowConnectRaw.event) )); } From bf1f6a2298fdfdd09060336417a5e892176200c7 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 17 Aug 2023 14:38:48 +0200 Subject: [PATCH 023/221] voice - update todos --- .../electron-sandbox/workbenchVoiceRecognitionService.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts b/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts index a676ed1aff5..7415d4dc6b5 100644 --- a/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts +++ b/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts @@ -62,8 +62,6 @@ class VoiceTranscriptionWorkletNode extends AudioWorkletNode { } // TODO@voice -// - how to prevent data processing accumulation when processing is slow? -// - how to make this a singleton service that enables ref-counting on multiple callers? // - voice module should directly transcribe the PCM32 data without wav+file conversion export class WorkbenchVoiceRecognitionService implements IWorkbenchVoiceRecognitionService { From 0e2849672fa62421435d8e49e86a2776681cdb39 Mon Sep 17 00:00:00 2001 From: Ulugbek Abdullaev Date: Thu, 17 Aug 2023 17:05:26 +0200 Subject: [PATCH 024/221] refactor: add types to remove warning --- src/vs/workbench/api/common/extHost.api.impl.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index 1673b845c0c..b48277a3d55 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -1340,7 +1340,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I checkProposedApiEnabled(extension, 'chatRequestAccess'); return extHostChatProvider.requestChatResponseProvider(extension.identifier, id); }, - registerVariable(name, description, resolver) { + registerVariable(name: string, description: string, resolver: vscode.ChatVariableResolver) { checkProposedApiEnabled(extension, 'chatVariables'); return extHostChatVariables.registerVariableResolver(extension, name, description, resolver); } From 3e9e7b3b5a31a6d07c5bd3b88184dce8bb82d896 Mon Sep 17 00:00:00 2001 From: Ulugbek Abdullaev Date: Thu, 17 Aug 2023 17:10:35 +0200 Subject: [PATCH 025/221] Initial implementation of `mappedEditsProvider` proposed API --- .../api/browser/extensionHost.contribution.ts | 1 + .../api/browser/mainThreadMappedEdits.ts | 57 ++++++++++++++++ .../workbench/api/common/extHost.api.impl.ts | 6 ++ .../workbench/api/common/extHost.protocol.ts | 21 ++++++ .../api/common/extHostMappedEdits.ts | 61 +++++++++++++++++ .../browser/actions/chatCodeblockActions.ts | 29 +++++++-- .../common/extensionsApiProposals.ts | 1 + .../mappedEdits/browser/mappedEditsService.ts | 51 +++++++++++++++ .../mappedEdits/common/mappedEdits.ts | 65 +++++++++++++++++++ src/vs/workbench/workbench.common.main.ts | 1 + .../vscode.proposed.mappedEditsProvider.d.ts | 48 ++++++++++++++ 11 files changed, 334 insertions(+), 7 deletions(-) create mode 100644 src/vs/workbench/api/browser/mainThreadMappedEdits.ts create mode 100644 src/vs/workbench/api/common/extHostMappedEdits.ts create mode 100644 src/vs/workbench/services/mappedEdits/browser/mappedEditsService.ts create mode 100644 src/vs/workbench/services/mappedEdits/common/mappedEdits.ts create mode 100644 src/vscode-dts/vscode.proposed.mappedEditsProvider.d.ts diff --git a/src/vs/workbench/api/browser/extensionHost.contribution.ts b/src/vs/workbench/api/browser/extensionHost.contribution.ts index 774cc0cc158..6d836e715e1 100644 --- a/src/vs/workbench/api/browser/extensionHost.contribution.ts +++ b/src/vs/workbench/api/browser/extensionHost.contribution.ts @@ -86,6 +86,7 @@ import './mainThreadTimeline'; import './mainThreadTesting'; import './mainThreadSecretState'; import './mainThreadShare'; +import './mainThreadMappedEdits'; import './mainThreadProfilContentHandlers'; import './mainThreadSemanticSimilarity'; import './mainThreadIssueReporter'; diff --git a/src/vs/workbench/api/browser/mainThreadMappedEdits.ts b/src/vs/workbench/api/browser/mainThreadMappedEdits.ts new file mode 100644 index 00000000000..a2a34f4155d --- /dev/null +++ b/src/vs/workbench/api/browser/mainThreadMappedEdits.ts @@ -0,0 +1,57 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { IDisposable, dispose } from 'vs/base/common/lifecycle'; +import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity'; +import { reviveWorkspaceEditDto } from 'vs/workbench/api/browser/mainThreadBulkEdits'; +import { ExtHostContext, ExtHostMappedEditsShape, IDocumentFilterDto, IMappedEditsContextDto, MainContext, MainThreadMappedEditsShape } from 'vs/workbench/api/common/extHost.protocol'; +import { IMappedEditsProvider, IMappedEditsService } from 'vs/workbench/services/mappedEdits/common/mappedEdits'; +import { IExtHostContext, extHostNamedCustomer } from 'vs/workbench/services/extensions/common/extHostCustomers'; + +@extHostNamedCustomer(MainContext.MainThreadMappedEdits) +export class MainThreadMappedEdits implements MainThreadMappedEditsShape { + + private readonly proxy: ExtHostMappedEditsShape; + + private providers = new Map(); + + private providerDisposables = new Map(); + + constructor( + extHostContext: IExtHostContext, + @IMappedEditsService private readonly mappedEditsService: IMappedEditsService, + @IUriIdentityService private readonly uriIdentityService: IUriIdentityService, + ) { + this.proxy = extHostContext.getProxy(ExtHostContext.ExtHostMappedEdits); + } + + $registerMappedEditsProvider(handle: number, selector: IDocumentFilterDto[]): void { + const provider: IMappedEditsProvider = { + selector, + provideMappedEdits: async (document, codeBlocks, context, token) => { + const result = await this.proxy.$provideMappedEdits(handle, document.uri, codeBlocks, context, token); + return result ? reviveWorkspaceEditDto(result, this.uriIdentityService) : null; + } + }; + this.providers.set(handle, provider); + const disposable = this.mappedEditsService.registerMappedEditsProvider(provider); + this.providerDisposables.set(handle, disposable); + } + + $unregisterMappedEditsProvider(handle: number): void { + if (this.providers.has(handle)) { + this.providers.delete(handle); + } + if (this.providerDisposables.has(handle)) { + this.providerDisposables.delete(handle); + } + } + + dispose(): void { + this.providers.clear(); + dispose(this.providerDisposables.values()); + this.providerDisposables.clear(); + } +} diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index b48277a3d55..055ed24f627 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -106,6 +106,7 @@ import { IExtHostManagedSockets } from 'vs/workbench/api/common/extHostManagedSo import { ExtHostShare } from 'vs/workbench/api/common/extHostShare'; import { ExtHostChatProvider } from 'vs/workbench/api/common/extHostChatProvider'; import { ExtHostChatSlashCommands } from 'vs/workbench/api/common/extHostChatSlashCommand'; +import { ExtHostMappedEdits } from 'vs/workbench/api/common/extHostMappedEdits'; import { ExtHostChatVariables } from 'vs/workbench/api/common/extHostChatVariables'; export interface IExtensionRegistries { @@ -210,6 +211,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I const extHostChatSlashCommands = rpcProtocol.set(ExtHostContext.ExtHostChatSlashCommands, new ExtHostChatSlashCommands(rpcProtocol, extHostChatProvider, extHostLogService)); const extHostChatVariables = rpcProtocol.set(ExtHostContext.ExtHostChatVariables, new ExtHostChatVariables(rpcProtocol)); const extHostChat = rpcProtocol.set(ExtHostContext.ExtHostChat, new ExtHostChat(rpcProtocol, extHostLogService)); + const extHostMappedEdits = rpcProtocol.set(ExtHostContext.ExtHostMappedEdits, new ExtHostMappedEdits(rpcProtocol, extHostDocuments, uriTransformer)); const extHostSemanticSimilarity = rpcProtocol.set(ExtHostContext.ExtHostSemanticSimilarity, new ExtHostSemanticSimilarity(rpcProtocol)); const extHostIssueReporter = rpcProtocol.set(ExtHostContext.ExtHostIssueReporter, new ExtHostIssueReporter(rpcProtocol)); const extHostStatusBar = rpcProtocol.set(ExtHostContext.ExtHostStatusBar, new ExtHostStatusBar(rpcProtocol, extHostCommands.converter)); @@ -1343,6 +1345,10 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I registerVariable(name: string, description: string, resolver: vscode.ChatVariableResolver) { checkProposedApiEnabled(extension, 'chatVariables'); return extHostChatVariables.registerVariableResolver(extension, name, description, resolver); + }, + registerMappedEditsProvider(selector: vscode.DocumentSelector, provider: vscode.MappedEditsProvider) { + checkProposedApiEnabled(extension, 'mappedEditsProvider'); + return extHostMappedEdits.registerMappedEditsProvider(selector, provider); } }; diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index 6886d86e0a9..686e4ad8af6 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -371,6 +371,16 @@ export interface IShareableItemDto { selection?: IRange; } +export interface IRelatedContextItemDto { + readonly uri: UriComponents; + readonly range: IRange; +} + +export interface IMappedEditsContextDto { + selections: ISelection[]; //FIXME@ulugbekna: is this serializable? should I use ISelection? + related: IRelatedContextItemDto[]; +} + export interface ISignatureHelpProviderMetadataDto { readonly triggerCharacters: readonly string[]; readonly retriggerCharacters: readonly string[]; @@ -1315,6 +1325,11 @@ export interface MainThreadShareShape extends IDisposable { $unregisterShareProvider(handle: number): void; } +export interface MainThreadMappedEditsShape extends IDisposable { + $registerMappedEditsProvider(handle: number, selector: IDocumentFilterDto[]): void; + $unregisterMappedEditsProvider(handle: number): void; +} + export interface MainThreadTaskShape extends IDisposable { $createTaskId(task: tasks.ITaskDTO): Promise; $registerTaskProvider(handle: number, type: string): Promise; @@ -2098,6 +2113,10 @@ export interface ExtHostShareShape { $provideShare(handle: number, shareableItem: IShareableItemDto, token: CancellationToken): Promise; } +export interface ExtHostMappedEditsShape { + $provideMappedEdits(handle: number, document: UriComponents, codeBlocks: string[], context: IMappedEditsContextDto, token: CancellationToken): Promise; +} + export interface ExtHostTaskShape { $provideTasks(handle: number, validTypes: { [key: string]: boolean }): Promise; $resolveTask(handle: number, taskDTO: tasks.ITaskDTO): Promise; @@ -2623,6 +2642,7 @@ export const MainContext = { MainThreadSCM: createProxyIdentifier('MainThreadSCM'), MainThreadSearch: createProxyIdentifier('MainThreadSearch'), MainThreadShare: createProxyIdentifier('MainThreadShare'), + MainThreadMappedEdits: createProxyIdentifier('MainThreadMappedEdits'), MainThreadTask: createProxyIdentifier('MainThreadTask'), MainThreadWindow: createProxyIdentifier('MainThreadWindow'), MainThreadLabelService: createProxyIdentifier('MainThreadLabelService'), @@ -2700,6 +2720,7 @@ export const ExtHostContext = { ExtHostChatSlashCommands: createProxyIdentifier('ExtHostChatSlashCommands'), ExtHostChatVariables: createProxyIdentifier('ExtHostChatVariables'), ExtHostChatProvider: createProxyIdentifier('ExtHostChatProvider'), + ExtHostMappedEdits: createProxyIdentifier('ExtHostMappedEdits'), ExtHostSemanticSimilarity: createProxyIdentifier('ExtHostSemanticSimilarity'), ExtHostTheming: createProxyIdentifier('ExtHostTheming'), ExtHostTunnelService: createProxyIdentifier('ExtHostTunnelService'), diff --git a/src/vs/workbench/api/common/extHostMappedEdits.ts b/src/vs/workbench/api/common/extHostMappedEdits.ts new file mode 100644 index 00000000000..c98adda03b2 --- /dev/null +++ b/src/vs/workbench/api/common/extHostMappedEdits.ts @@ -0,0 +1,61 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { CancellationToken } from 'vs/base/common/cancellation'; +import { URI, UriComponents } from 'vs/base/common/uri'; +import { IURITransformer } from 'vs/base/common/uriIpc'; +import { ExtHostMappedEditsShape, IMainContext, IMappedEditsContextDto, IWorkspaceEditDto, MainContext, MainThreadMappedEditsShape } from 'vs/workbench/api/common/extHost.protocol'; +import { ExtHostDocuments } from 'vs/workbench/api/common/extHostDocuments'; +import { Range, Selection, DocumentSelector, WorkspaceEdit } from 'vs/workbench/api/common/extHostTypeConverters'; +import type * as vscode from 'vscode'; + +export class ExtHostMappedEdits implements ExtHostMappedEditsShape { + + private static handlePool: number = 0; + + private proxy: MainThreadMappedEditsShape; + private providers = new Map(); + + constructor( + mainContext: IMainContext, + private readonly _documents: ExtHostDocuments, + private readonly uriTransformer: IURITransformer | undefined + ) { + this.proxy = mainContext.getProxy(MainContext.MainThreadMappedEdits); + } + + async $provideMappedEdits(handle: number, docUri: UriComponents, codeBlocks: string[], context: IMappedEditsContextDto, token: CancellationToken): Promise { + const provider = this.providers.get(handle); + if (!provider) { + return null; + } + const uri = URI.revive(docUri); + const doc = this._documents.getDocument(uri); + const ctx = { + selections: context.selections.map(s => Selection.to(s)), + related: context.related.map(r => ({ uri: URI.revive(r.uri), range: Range.to(r.range) })), + }; + const mappedEdits = await provider.provideMappedEdits(doc, codeBlocks, ctx, token); + if (!mappedEdits) { + return null; + } + + return WorkspaceEdit.from(mappedEdits); + } + + registerMappedEditsProvider(selector: vscode.DocumentSelector, provider: vscode.MappedEditsProvider): vscode.Disposable { + const handle = ExtHostMappedEdits.handlePool++; + this.providers.set(handle, provider); + this.proxy.$registerMappedEditsProvider(handle, DocumentSelector.from(selector, this.uriTransformer)); + return { + dispose: () => { + ExtHostMappedEdits.handlePool--; + this.proxy.$unregisterMappedEditsProvider(handle); + this.providers.delete(handle); + } + }; + } + +} diff --git a/src/vs/workbench/contrib/chat/browser/actions/chatCodeblockActions.ts b/src/vs/workbench/contrib/chat/browser/actions/chatCodeblockActions.ts index e9c9089baf6..85fd1ee7ad2 100644 --- a/src/vs/workbench/contrib/chat/browser/actions/chatCodeblockActions.ts +++ b/src/vs/workbench/contrib/chat/browser/actions/chatCodeblockActions.ts @@ -3,6 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { CancellationTokenSource } from 'vs/base/common/cancellation'; import { Codicon } from 'vs/base/common/codicons'; import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; import { ICodeEditor, isCodeEditor, isDiffEditor } from 'vs/editor/browser/editorBrowser'; @@ -24,6 +25,7 @@ import { IChatWidgetService } from 'vs/workbench/contrib/chat/browser/chat'; import { CONTEXT_IN_CHAT_SESSION, CONTEXT_PROVIDER_EXISTS } from 'vs/workbench/contrib/chat/common/chatContextKeys'; import { IChatCopyAction, IChatService, IChatUserActionEvent, InteractiveSessionCopyKind } from 'vs/workbench/contrib/chat/common/chatService'; import { IChatResponseViewModel, isResponseVM } from 'vs/workbench/contrib/chat/common/chatViewModel'; +import { IMappedEditsService, RelatedContextItem } from 'vs/workbench/services/mappedEdits/common/mappedEdits'; import { insertCell } from 'vs/workbench/contrib/notebook/browser/controller/cellOperations'; import { INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { CellKind, NOTEBOOK_EDITOR_ID } from 'vs/workbench/contrib/notebook/common/notebookCommon'; @@ -232,17 +234,30 @@ export function registerChatCodeBlockActions() { this.notifyUserAction(accessor, context); } - private async handleTextEditor(accessor: ServicesAccessor, codeEditor: ICodeEditor, activeModel: ITextModel, context: IChatCodeBlockActionContext) { - this.notifyUserAction(accessor, context); + private async handleTextEditor(accessor: ServicesAccessor, codeEditor: ICodeEditor, activeModel: ITextModel, chatCodeBlockActionContext: IChatCodeBlockActionContext) { + this.notifyUserAction(accessor, chatCodeBlockActionContext); const bulkEditService = accessor.get(IBulkEditService); const codeEditorService = accessor.get(ICodeEditorService); + const mappedEditsService = accessor.get(IMappedEditsService); - const activeSelection = codeEditor.getSelection() ?? new Range(activeModel.getLineCount(), 1, activeModel.getLineCount(), 1); - await bulkEditService.apply([new ResourceTextEdit(activeModel.uri, { - range: activeSelection, - text: context.code, - })]); + // try applying workspace edit that was returned by a MappedEditsProvider, else simply insert at selection + const selections = codeEditor.getSelections() ?? []; + const mappedEditsContext = { + selections, + related: [] as RelatedContextItem[], // FIXME@ulugbekna: this needs to be populated but we don't yet have a way to get this info from extensions + }; + const cancellationTokenSource = new CancellationTokenSource(); + const workspaceEdit = await mappedEditsService.provideMappedEdits(activeModel, [chatCodeBlockActionContext.code], mappedEditsContext, cancellationTokenSource.token); + if (workspaceEdit) { + await bulkEditService.apply(workspaceEdit); + } else { + const activeSelection = codeEditor.getSelection() ?? new Range(activeModel.getLineCount(), 1, activeModel.getLineCount(), 1); + await bulkEditService.apply([new ResourceTextEdit(activeModel.uri, { + range: activeSelection, + text: chatCodeBlockActionContext.code, + })]); + } codeEditorService.listCodeEditors().find(editor => editor.getModel()?.uri.toString() === activeModel.uri.toString())?.focus(); } diff --git a/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts b/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts index f3dc351a3a5..dd1794371f0 100644 --- a/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts +++ b/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts @@ -58,6 +58,7 @@ export const allApiProposals = Object.freeze({ interactiveWindow: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.interactiveWindow.d.ts', ipc: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.ipc.d.ts', languageConfigurationAutoClosingPairs: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.languageConfigurationAutoClosingPairs.d.ts', + mappedEditsProvider: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.mappedEditsProvider.d.ts', notebookCellExecutionState: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.notebookCellExecutionState.d.ts', notebookCodeActions: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.notebookCodeActions.d.ts', notebookControllerAffinityHidden: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.notebookControllerAffinityHidden.d.ts', diff --git a/src/vs/workbench/services/mappedEdits/browser/mappedEditsService.ts b/src/vs/workbench/services/mappedEdits/browser/mappedEditsService.ts new file mode 100644 index 00000000000..fe1cec5815a --- /dev/null +++ b/src/vs/workbench/services/mappedEdits/browser/mappedEditsService.ts @@ -0,0 +1,51 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { CancellationToken } from 'vs/base/common/cancellation'; +import { ITextModel } from 'vs/editor/common/model'; +import { IMappedEditsProvider, IMappedEditsService, MappedEditsContext } from 'vs/workbench/services/mappedEdits/common/mappedEdits'; +import { score } from 'vs/editor/common/languageSelector'; +import { WorkspaceEdit } from 'vs/editor/common/languages'; +import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions'; + +export class MappedEditsService implements IMappedEditsService { + readonly _serviceBrand: undefined; + + private readonly _providers = new Set(); + + constructor() { } + + registerMappedEditsProvider(provider: IMappedEditsProvider) { + this._providers.add(provider); + return { + dispose: () => { + this._providers.delete(provider); + } + }; + } + + async provideMappedEdits(document: ITextModel, codeBlocks: string[], context: MappedEditsContext, token: CancellationToken): Promise { + + const language = document.getLanguageId(); + + const providers = [...this._providers.values()] + .map((p): [IMappedEditsProvider, number] => { + const pts = score(p.selector, document.uri, language, true, undefined, undefined); + return [p, pts]; + }) + .filter(([p, pts]) => pts > 0) + .sort((a, b) => b[1] - a[1]); + + if (providers.length === 0) { + return null; + } + + const provider = providers[0][0]; + + return provider.provideMappedEdits(document, codeBlocks, context, token); + } +} + +registerSingleton(IMappedEditsService, MappedEditsService, InstantiationType.Delayed); diff --git a/src/vs/workbench/services/mappedEdits/common/mappedEdits.ts b/src/vs/workbench/services/mappedEdits/common/mappedEdits.ts new file mode 100644 index 00000000000..8e58c5c1031 --- /dev/null +++ b/src/vs/workbench/services/mappedEdits/common/mappedEdits.ts @@ -0,0 +1,65 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { URI } from 'vs/base/common/uri'; +import { ITextModel } from 'vs/editor/common/model'; +import { CancellationToken } from 'vs/base/common/cancellation'; +import { LanguageSelector } from 'vs/editor/common/languageSelector'; +import { IDisposable } from 'vs/base/common/lifecycle'; +import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; +import { WorkspaceEdit } from 'vs/editor/common/languages'; +import { Selection } from 'vs/editor/common/core/selection'; +import { Range } from 'vs/editor/common/core/range'; + +export interface RelatedContextItem { + readonly uri: URI; + readonly range: Range; +} + +export interface MappedEditsContext { + selections: Selection[]; + + /** + * If there's no context, the array should be empty. It's also empty until we figure out how to compute this or retrieve from an extension (eg, copilot chat) + * + * TODO@ulugbekna: should this array be sorted from highest priority to lowest? + */ + related: RelatedContextItem[]; +} + +export interface IMappedEditsProvider { + + selector: LanguageSelector; + + /** + * Provide mapped edits for a given document. + * + * @param document The document to provide mapped edits for. + * @param codeBlocks Code blocks that come from an LLM's reply. + * "Insert at cursor" in the panel chat only sends one edit that the user clicks on, but inline chat can send multiple blocks and let the lang server decide what to do with them. + * @param context The context for providing mapped edits. + * @param token A cancellation token. + * @returns A provider result of text edits. + */ + provideMappedEdits( + document: ITextModel, + codeBlocks: string[], + context: MappedEditsContext, + token: CancellationToken + ): Promise; +} + + +export const IMappedEditsService = createDecorator('mappedEditsService'); + +export interface IMappedEditsService { + _serviceBrand: undefined; + registerMappedEditsProvider(provider: IMappedEditsProvider): IDisposable; + provideMappedEdits( + document: ITextModel, + codeBlocks: string[], + context: MappedEditsContext, + token: CancellationToken): Promise; +} diff --git a/src/vs/workbench/workbench.common.main.ts b/src/vs/workbench/workbench.common.main.ts index a52b2b4c274..81170dfd99e 100644 --- a/src/vs/workbench/workbench.common.main.ts +++ b/src/vs/workbench/workbench.common.main.ts @@ -111,6 +111,7 @@ import 'vs/workbench/services/textMate/browser/textMateTokenizationFeature.contr import 'vs/workbench/services/userActivity/common/userActivityService'; import 'vs/workbench/services/userActivity/browser/userActivityBrowser'; import 'vs/workbench/services/issue/browser/issueTroubleshoot'; +import 'vs/workbench/services/mappedEdits/browser/mappedEditsService'; import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { ExtensionGalleryService } from 'vs/platform/extensionManagement/common/extensionGalleryService'; diff --git a/src/vscode-dts/vscode.proposed.mappedEditsProvider.d.ts b/src/vscode-dts/vscode.proposed.mappedEditsProvider.d.ts new file mode 100644 index 00000000000..9d05e467fd9 --- /dev/null +++ b/src/vscode-dts/vscode.proposed.mappedEditsProvider.d.ts @@ -0,0 +1,48 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +declare module 'vscode' { + + export interface RelatedContextItem { + readonly uri: Uri; + readonly range: Range; + } + + export interface MappedEditsContext { + selections: Selection[]; + + /** + * If there's no context, the array should be empty. It's also empty until we figure out how to compute this or retrieve from an extension (eg, copilot chat) + * + * TODO: it was suggested initially to be sorted from highest priority to lowest. How would it look like? + */ + related: RelatedContextItem[]; + } + + /** + * Interface for providing mapped edits for a given document. + */ + export interface MappedEditsProvider { + /** + * Provide mapped edits for a given document. + * @param document The document to provide mapped edits for. + * @param codeBlocks Code blocks that come from an LLM's reply. + * "Insert at cursor" in the panel chat only sends one edit that the user clicks on, but inline chat can send multiple blocks and let the lang server decide what to do with them. + * @param context The context for providing mapped edits. + * @param token A cancellation token. + * @returns A provider result of text edits. + */ + provideMappedEdits( + document: TextDocument, + codeBlocks: string[], + context: MappedEditsContext, + token: CancellationToken + ): ProviderResult; + } + + namespace chat { + export function registerMappedEditsProvider(documentSelector: DocumentSelector, provider: MappedEditsProvider): Disposable; + } +} From 81ae16ba6efea382fdb068c8859fcd116c767550 Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Fri, 18 Aug 2023 10:47:35 +0200 Subject: [PATCH 026/221] sending the telemetry event in a loop --- .../src/languageFeatures/diagnostics.ts | 102 +++++++++++------- .../src/typescriptServiceClient.ts | 2 +- 2 files changed, 63 insertions(+), 41 deletions(-) diff --git a/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts b/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts index 8a4a0c79e95..73495fb3301 100644 --- a/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts +++ b/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts @@ -9,6 +9,7 @@ import * as arrays from '../utils/arrays'; import { Disposable } from '../utils/dispose'; import { ResourceMap } from '../utils/resourceMap'; import { TelemetryReporter } from '../logging/telemetry'; +import { URI } from 'vscode-uri'; function diagnosticsEquals(a: vscode.Diagnostic, b: vscode.Diagnostic): boolean { if (a === b) { @@ -149,31 +150,68 @@ class DiagnosticSettings { } } -class DiagnosticsTelemetryManager { +/* +const diagnostics = this.getDiagnostics(document.uri); + const diagnoticCodes = diagnostics.reduce(function (result: number[], d: vscode.Diagnostic) { + const code = d.code; + if (typeof code === 'string' || typeof code === 'number') { + result.push(Number(code)); + } else if (code !== undefined) { + result.push(Number(code.value)); + } + return result; + }, []); + */ +class DiagnosticsTelemetryManager extends Disposable { - private _diagnosticCodes: number[] = []; + private readonly _timeOutDiagnosticMaps = new Map(); + private readonly _diagnosticCodesMap = new Map(); - constructor(private readonly _telemetryReporter: TelemetryReporter) { } - - public addDiagnosticCodes(codes: number[]) { - this._diagnosticCodes.push(...codes); - this._diagnosticCodes.sort(); + constructor(private readonly _telemetryReporter: TelemetryReporter) { + super(); + this._register(vscode.workspace.onDidChangeTextDocument(e => { + if (e.document.languageId === 'typescript') { + clearTimeout(this._timeOutDiagnosticMaps.get(e.document.uri)); + const timeOut = setTimeout(() => { }, 5000); + this._timeOutDiagnosticMaps.set(e.document.uri, timeOut); + } + })); + this._register(vscode.workspace.onDidOpenTextDocument(e => { + if (e.languageId === 'typescript') { + this._timeOutDiagnosticMaps.set(e.uri, undefined); + } + })); + this._register(vscode.workspace.onDidCloseTextDocument(e => { + if (e.languageId === 'typescript') { + this._timeOutDiagnosticMaps.delete(e.uri); + } + })); + this._sendTelemetryEvent(); } - public sendDiagnosticsCodesTelemetry(): void { - /* __GDPR__ - "typescript.diagnostics" : { - "owner": "@aiday-mar", - "diagnosticCodes" : { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" }, - "${include}": [ - "${TypeScriptCommonProperties}" - ] - } - */ - this._telemetryReporter.logTelemetry('typescript.diagnostics', { - diagnoticCodes: this._diagnosticCodes.join(', ') - }); - this._diagnosticCodes = []; + private _sendTelemetryEvent() { + setTimeout(() => { + if (this._diagnosticCodesMap.size > 0) { + let diagnosticCodes = ''; + this._diagnosticCodesMap.forEach((value, key) => { + diagnosticCodes += `${key}:${value},`; + }); + this._diagnosticCodesMap.clear(); + /* __GDPR__ + "typescript.diagnostics" : { + "owner": "@aiday-mar", + "diagnosticCodes" : { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" }, + "${include}": [ + "${TypeScriptCommonProperties}" + ] + } + */ + this._telemetryReporter.logTelemetry('typescript.diagnostics', { + diagnoticCodes: diagnosticCodes + }); + } + this._sendTelemetryEvent(); + }, 5 * 60 * 1000); } } @@ -182,7 +220,6 @@ export class DiagnosticsManager extends Disposable { private readonly _settings = new DiagnosticSettings(); private readonly _currentDiagnostics: vscode.DiagnosticCollection; private readonly _pendingUpdates: ResourceMap; - private readonly _diagnosticsTelemetryManager: DiagnosticsTelemetryManager; private readonly _updateDelay = 50; constructor( @@ -195,24 +232,9 @@ export class DiagnosticsManager extends Disposable { this._pendingUpdates = new ResourceMap(undefined, { onCaseInsensitiveFileSystem }); this._currentDiagnostics = this._register(vscode.languages.createDiagnosticCollection(owner)); - this._diagnosticsTelemetryManager = new DiagnosticsTelemetryManager(telemetryReporter); - this._register(vscode.workspace.onDidOpenTextDocument((document) => { - const diagnostics = this.getDiagnostics(document.uri); - const diagnoticCodes = diagnostics.reduce(function (result: number[], d: vscode.Diagnostic) { - const code = d.code; - if (typeof code === 'string' || typeof code === 'number') { - result.push(Number(code)); - } else if (code !== undefined) { - result.push(Number(code.value)); - } - return result; - }, []); - this._diagnosticsTelemetryManager.addDiagnosticCodes(diagnoticCodes); - })); - } - - public sendDiagnosticsCodesTelemetry(): void { - this._diagnosticsTelemetryManager.sendDiagnosticsCodesTelemetry(); + if (Math.random() * 1000 <= 1) { + this._register(new DiagnosticsTelemetryManager(telemetryReporter)); + } } public override dispose() { diff --git a/extensions/typescript-language-features/src/typescriptServiceClient.ts b/extensions/typescript-language-features/src/typescriptServiceClient.ts index d04f41e4142..c165f82db40 100644 --- a/extensions/typescript-language-features/src/typescriptServiceClient.ts +++ b/extensions/typescript-language-features/src/typescriptServiceClient.ts @@ -456,7 +456,7 @@ export default class TypeScriptServiceClient extends Disposable implements IType } */ this.logTelemetry('tsserver.exitWithCode', { code: code ?? undefined, signal: signal ?? undefined }); - this.diagnosticsManager.sendDiagnosticsCodesTelemetry(); + if (this.token !== mytoken) { // this is coming from an old process From 008b00d24f3c3d8d89f70513bc9e1d5b164045fc Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Fri, 18 Aug 2023 11:33:03 +0200 Subject: [PATCH 027/221] taking the diff between current and previous snapshot --- .../src/languageFeatures/diagnostics.ts | 27 ++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts b/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts index 73495fb3301..4331278c4ff 100644 --- a/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts +++ b/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts @@ -10,6 +10,7 @@ import { Disposable } from '../utils/dispose'; import { ResourceMap } from '../utils/resourceMap'; import { TelemetryReporter } from '../logging/telemetry'; import { URI } from 'vscode-uri'; +import { diff } from 'semver'; function diagnosticsEquals(a: vscode.Diagnostic, b: vscode.Diagnostic): boolean { if (a === b) { @@ -165,14 +166,18 @@ const diagnostics = this.getDiagnostics(document.uri); class DiagnosticsTelemetryManager extends Disposable { private readonly _timeOutDiagnosticMaps = new Map(); + private readonly _diagnosticsSnapshot = new Map(); private readonly _diagnosticCodesMap = new Map(); - constructor(private readonly _telemetryReporter: TelemetryReporter) { + constructor( + private readonly _telemetryReporter: TelemetryReporter, + private readonly _getDiagnostics: (uri: URI) => readonly vscode.Diagnostic[] + ) { super(); this._register(vscode.workspace.onDidChangeTextDocument(e => { if (e.document.languageId === 'typescript') { clearTimeout(this._timeOutDiagnosticMaps.get(e.document.uri)); - const timeOut = setTimeout(() => { }, 5000); + const timeOut = setTimeout(() => { this._updateDiagnosticCodes(e.document.uri); }, 5000); this._timeOutDiagnosticMaps.set(e.document.uri, timeOut); } })); @@ -189,6 +194,21 @@ class DiagnosticsTelemetryManager extends Disposable { this._sendTelemetryEvent(); } + private _updateDiagnosticCodes(uri: URI) { + const previousDiagnostics = this._diagnosticsSnapshot.get(uri); + const currentDiagnostics = this._getDiagnostics(uri); + this._diagnosticsSnapshot.set(uri, currentDiagnostics); + const diagnosticsDiff = currentDiagnostics.filter((diagnostic) => !previousDiagnostics?.some((previousDiagnostic) => JSON.stringify(diagnostic) === JSON.stringify(previousDiagnostic))); + diagnosticsDiff.forEach((diagnostic) => { + const code = diagnostic.code; + if (typeof code === 'string' || typeof code === 'number') { + this._diagnosticCodesMap.set(Number(code), (this._diagnosticCodesMap.get(Number(code)) || 0) + 1); + } else if (code !== undefined) { + this._diagnosticCodesMap.set(Number(code.value), (this._diagnosticCodesMap.get(Number(code.value)) || 0) + 1); + } + }); + } + private _sendTelemetryEvent() { setTimeout(() => { if (this._diagnosticCodesMap.size > 0) { @@ -220,6 +240,7 @@ export class DiagnosticsManager extends Disposable { private readonly _settings = new DiagnosticSettings(); private readonly _currentDiagnostics: vscode.DiagnosticCollection; private readonly _pendingUpdates: ResourceMap; + private readonly _updateDelay = 50; constructor( @@ -233,7 +254,7 @@ export class DiagnosticsManager extends Disposable { this._currentDiagnostics = this._register(vscode.languages.createDiagnosticCollection(owner)); if (Math.random() * 1000 <= 1) { - this._register(new DiagnosticsTelemetryManager(telemetryReporter)); + this._register(new DiagnosticsTelemetryManager(telemetryReporter, this.getDiagnostics)); } } From 088f7cf83241acc0d67657b2885b55f9c76c5d4f Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 18 Aug 2023 11:50:37 +0200 Subject: [PATCH 028/221] voice - only send new data to voice transcriber --- .../sharedProcess/contrib/voiceTranscriber.ts | 32 ++++++++++++++++--- .../node/sharedProcess/sharedProcessMain.ts | 3 +- .../common/voiceRecognitionService.ts | 26 --------------- .../node/voiceRecognitionService.ts | 21 +++++++++++- .../voiceTranscriptionWorklet.ts | 28 ++++------------ .../workbenchVoiceRecognitionService.ts | 3 +- 6 files changed, 56 insertions(+), 57 deletions(-) delete mode 100644 src/vs/platform/voiceRecognition/common/voiceRecognitionService.ts diff --git a/src/vs/code/node/sharedProcess/contrib/voiceTranscriber.ts b/src/vs/code/node/sharedProcess/contrib/voiceTranscriber.ts index 6b8f8bf3084..d9a9979dcb3 100644 --- a/src/vs/code/node/sharedProcess/contrib/voiceTranscriber.ts +++ b/src/vs/code/node/sharedProcess/contrib/voiceTranscriber.ts @@ -6,7 +6,7 @@ import { Event } from 'vs/base/common/event'; import { MessagePortMain, MessageEvent } from 'vs/base/parts/sandbox/node/electronTypes'; import { Disposable, toDisposable } from 'vs/base/common/lifecycle'; -import { IVoiceRecognitionService } from 'vs/platform/voiceRecognition/common/voiceRecognitionService'; +import { IVoiceRecognitionService } from 'vs/platform/voiceRecognition/node/voiceRecognitionService'; import { ILogService } from 'vs/platform/log/common/log'; import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation'; import { TaskSequentializer } from 'vs/base/common/async'; @@ -36,6 +36,8 @@ class VoiceTranscriber extends Disposable { private requests = 0; + private data: Float32Array | undefined = undefined; + constructor( private readonly port: MessagePortMain, private readonly voiceRecognitionService: IVoiceRecognitionService, @@ -68,16 +70,26 @@ class VoiceTranscriber extends Disposable { } private async handleRequest(e: MessageEvent, cancellation: CancellationToken): Promise { - if (!(e.data instanceof Float32Array)) { + if (!(Array.isArray(e.data))) { return; } + const newData: Float32Array[] = []; + for (const channelData of e.data) { + if (channelData instanceof Float32Array) { + newData.push(channelData); + } + } + + this.data = this.joinFloat32Arrays(this.data ? [this.data, ...newData] : newData); + const data = this.data.slice(0); + this.requests++; if (!this.transcriptionSequentializer.hasPending()) { - this.transcriptionSequentializer.setPending(this.requests, this.transcribe(e.data, cancellation)); + this.transcriptionSequentializer.setPending(this.requests, this.transcribe(data, cancellation)); } else { - this.transcriptionSequentializer.setNext(() => this.transcribe(e.data, cancellation)); + this.transcriptionSequentializer.setNext(() => this.transcribe(data, cancellation)); } } @@ -94,4 +106,16 @@ class VoiceTranscriber extends Disposable { this.port.postMessage(result); } + + private joinFloat32Arrays(float32Arrays: Float32Array[]): Float32Array { + const result = new Float32Array(float32Arrays.reduce((prev, curr) => prev + curr.length, 0)); + + let offset = 0; + for (const float32Array of float32Arrays) { + result.set(float32Array, offset); + offset += float32Array.length; + } + + return result; + } } diff --git a/src/vs/code/node/sharedProcess/sharedProcessMain.ts b/src/vs/code/node/sharedProcess/sharedProcessMain.ts index bf30c403b93..a81bedb9ab4 100644 --- a/src/vs/code/node/sharedProcess/sharedProcessMain.ts +++ b/src/vs/code/node/sharedProcess/sharedProcessMain.ts @@ -114,8 +114,7 @@ import { IRemoteSocketFactoryService, RemoteSocketFactoryService } from 'vs/plat import { RemoteConnectionType } from 'vs/platform/remote/common/remoteAuthorityResolver'; import { nodeSocketFactory } from 'vs/platform/remote/node/nodeSocketFactory'; import { NativeEnvironmentService } from 'vs/platform/environment/node/environmentService'; -import { IVoiceRecognitionService } from 'vs/platform/voiceRecognition/common/voiceRecognitionService'; -import { VoiceRecognitionService } from 'vs/platform/voiceRecognition/node/voiceRecognitionService'; +import { IVoiceRecognitionService, VoiceRecognitionService } from 'vs/platform/voiceRecognition/node/voiceRecognitionService'; import { VoiceTranscriptionManager } from 'vs/code/node/sharedProcess/contrib/voiceTranscriber'; import { SharedProcessRawConnection, SharedProcessLifecycle } from 'vs/platform/sharedProcess/common/sharedProcess'; diff --git a/src/vs/platform/voiceRecognition/common/voiceRecognitionService.ts b/src/vs/platform/voiceRecognition/common/voiceRecognitionService.ts deleted file mode 100644 index ca52963092f..00000000000 --- a/src/vs/platform/voiceRecognition/common/voiceRecognitionService.ts +++ /dev/null @@ -1,26 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { CancellationToken } from 'vs/base/common/cancellation'; -import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; - -export const IVoiceRecognitionService = createDecorator('voiceRecognitionService'); - -export interface IVoiceRecognitionService { - - readonly _serviceBrand: undefined; - - /** - * Given a buffer of audio data, attempts to - * transcribe the spoken words into text. - * - * @param channelData the raw audio data obtained - * from the microphone as uncompressed PCM data: - * - 1 channel (mono) - * - 16khz sampling rate - * - 16bit sample size - */ - transcribe(channelData: Float32Array, cancellation: CancellationToken): Promise; -} diff --git a/src/vs/platform/voiceRecognition/node/voiceRecognitionService.ts b/src/vs/platform/voiceRecognition/node/voiceRecognitionService.ts index f1e259b76ad..ca569eae27e 100644 --- a/src/vs/platform/voiceRecognition/node/voiceRecognitionService.ts +++ b/src/vs/platform/voiceRecognition/node/voiceRecognitionService.ts @@ -5,7 +5,26 @@ import { CancellationToken } from 'vs/base/common/cancellation'; import { ILogService } from 'vs/platform/log/common/log'; -import { IVoiceRecognitionService } from 'vs/platform/voiceRecognition/common/voiceRecognitionService'; +import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; + +export const IVoiceRecognitionService = createDecorator('voiceRecognitionService'); + +export interface IVoiceRecognitionService { + + readonly _serviceBrand: undefined; + + /** + * Given a buffer of audio data, attempts to + * transcribe the spoken words into text. + * + * @param channelData the raw audio data obtained + * from the microphone as uncompressed PCM data: + * - 1 channel (mono) + * - 16khz sampling rate + * - 16bit sample size + */ + transcribe(channelData: Float32Array, cancellation: CancellationToken): Promise; +} export class VoiceRecognitionService implements IVoiceRecognitionService { diff --git a/src/vs/workbench/services/voiceRecognition/electron-sandbox/voiceTranscriptionWorklet.ts b/src/vs/workbench/services/voiceRecognition/electron-sandbox/voiceTranscriptionWorklet.ts index d6edf688d1f..a298b23b29d 100644 --- a/src/vs/workbench/services/voiceRecognition/electron-sandbox/voiceTranscriptionWorklet.ts +++ b/src/vs/workbench/services/voiceRecognition/electron-sandbox/voiceTranscriptionWorklet.ts @@ -15,14 +15,12 @@ class VoiceTranscriptionWorklet extends AudioWorkletProcessor { private static readonly BUFFER_TIMESPAN = 2000; private startTime: number | undefined = undefined; + private stopped: boolean = false; - private allInputFloat32Array: Float32Array | undefined = undefined; - private currentInputFloat32Arrays: Float32Array[] = []; + private buffer: Float32Array[] = []; private sharedProcessConnection: MessagePort | undefined = undefined; - private stopped: boolean = false; - constructor() { super(); @@ -71,33 +69,19 @@ class VoiceTranscriptionWorklet extends AudioWorkletProcessor { return !this.stopped; } - this.currentInputFloat32Arrays.push(inputChannelData.slice(0)); + this.buffer.push(inputChannelData.slice(0)); if (Date.now() - this.startTime > VoiceTranscriptionWorklet.BUFFER_TIMESPAN && this.sharedProcessConnection) { - const currentInputFloat32Arrays = this.currentInputFloat32Arrays; - this.currentInputFloat32Arrays = []; + const buffer = this.buffer; + this.buffer = []; - this.allInputFloat32Array = this.joinFloat32Arrays(this.allInputFloat32Array ? [this.allInputFloat32Array, ...currentInputFloat32Arrays] : currentInputFloat32Arrays); - - this.sharedProcessConnection.postMessage(this.allInputFloat32Array); + this.sharedProcessConnection.postMessage(buffer); this.startTime = Date.now(); } return !this.stopped; } - - private joinFloat32Arrays(float32Arrays: Float32Array[]): Float32Array { - const result = new Float32Array(float32Arrays.reduce((acc, curr) => acc + curr.length, 0)); - - let offset = 0; - for (const float32Array of float32Arrays) { - result.set(float32Array, offset); - offset += float32Array.length; - } - - return result; - } } // @ts-ignore diff --git a/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts b/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts index 7415d4dc6b5..17260848ccf 100644 --- a/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts +++ b/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts @@ -62,8 +62,7 @@ class VoiceTranscriptionWorkletNode extends AudioWorkletNode { } // TODO@voice -// - voice module should directly transcribe the PCM32 data without wav+file conversion - +// - pass cancellation down into the node module via AbortSignal export class WorkbenchVoiceRecognitionService implements IWorkbenchVoiceRecognitionService { declare readonly _serviceBrand: undefined; From c71094a794e4ffbc7592269ef0960f4a187dea8a Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 18 Aug 2023 12:03:18 +0200 Subject: [PATCH 029/221] voice - stop processing after 30s --- .../node/sharedProcess/contrib/voiceTranscriber.ts | 11 ++++++++++- .../voiceRecognition/node/voiceRecognitionService.ts | 6 +++--- .../workbenchVoiceRecognitionService.ts | 10 +++++----- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/vs/code/node/sharedProcess/contrib/voiceTranscriber.ts b/src/vs/code/node/sharedProcess/contrib/voiceTranscriber.ts index d9a9979dcb3..210570ef952 100644 --- a/src/vs/code/node/sharedProcess/contrib/voiceTranscriber.ts +++ b/src/vs/code/node/sharedProcess/contrib/voiceTranscriber.ts @@ -32,6 +32,8 @@ export class VoiceTranscriptionManager extends Disposable { class VoiceTranscriber extends Disposable { + private static MAX_DATA_LENGTH = 30 /* seconds */ * 16000 /* sampling rate */ * 16 /* bith depth */ * 1 /* channels */ / 8; + private readonly transcriptionSequentializer = new TaskSequentializer(); private requests = 0; @@ -81,7 +83,14 @@ class VoiceTranscriber extends Disposable { } } - this.data = this.joinFloat32Arrays(this.data ? [this.data, ...newData] : newData); + const dataCandidate = this.joinFloat32Arrays(this.data ? [this.data, ...newData] : newData); + + if (dataCandidate.length > VoiceTranscriber.MAX_DATA_LENGTH) { + this.logService.warn(`[voice] transcriber: refusing to accept more than 30s of audio data`); + return; + } + + this.data = dataCandidate; const data = this.data.slice(0); this.requests++; diff --git a/src/vs/platform/voiceRecognition/node/voiceRecognitionService.ts b/src/vs/platform/voiceRecognition/node/voiceRecognitionService.ts index ca569eae27e..a2a1d3218e9 100644 --- a/src/vs/platform/voiceRecognition/node/voiceRecognitionService.ts +++ b/src/vs/platform/voiceRecognition/node/voiceRecognitionService.ts @@ -44,11 +44,11 @@ export class VoiceRecognitionService implements IVoiceRecognitionService { const now = Date.now(); - const voiceModule: { transcribe: (audioBuffer: { channelCount: 1; sampleRate: 16000; sampleSize: 16; channelData: Float32Array }, options: { language: string | 'auto'; suppressNonSpeechTokens: boolean }) => Promise } = require.__$__nodeRequire(modulePath); + const voiceModule: { transcribe: (audioBuffer: { channelCount: 1; samplingRate: 16000; bitDepth: 16; channelData: Float32Array }, options: { language: string | 'auto'; suppressNonSpeechTokens: boolean }) => Promise } = require.__$__nodeRequire(modulePath); const text = await voiceModule.transcribe({ - sampleRate: 16000, - sampleSize: 16, + samplingRate: 16000, + bitDepth: 16, channelCount: 1, channelData }, { diff --git a/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts b/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts index 17260848ccf..e2e94971c3a 100644 --- a/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts +++ b/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts @@ -67,8 +67,8 @@ export class WorkbenchVoiceRecognitionService implements IWorkbenchVoiceRecognit declare readonly _serviceBrand: undefined; - private static readonly AUDIO_SAMPLE_RATE = 16000; - private static readonly AUDIO_SAMPLE_SIZE = 16; + private static readonly AUDIO_SAMPLING_RATE = 16000; + private static readonly AUDIO_BIT_DEPTH = 16; private static readonly AUDIO_CHANNELS = 1; constructor( @@ -96,8 +96,8 @@ export class WorkbenchVoiceRecognitionService implements IWorkbenchVoiceRecognit const microphoneDevice = await navigator.mediaDevices.getUserMedia({ audio: { - sampleRate: WorkbenchVoiceRecognitionService.AUDIO_SAMPLE_RATE, - sampleSize: WorkbenchVoiceRecognitionService.AUDIO_SAMPLE_SIZE, + sampleRate: WorkbenchVoiceRecognitionService.AUDIO_SAMPLING_RATE, + sampleSize: WorkbenchVoiceRecognitionService.AUDIO_BIT_DEPTH, channelCount: WorkbenchVoiceRecognitionService.AUDIO_CHANNELS, autoGainControl: true, noiseSuppression: true @@ -109,7 +109,7 @@ export class WorkbenchVoiceRecognitionService implements IWorkbenchVoiceRecognit } const audioContext = new AudioContext({ - sampleRate: WorkbenchVoiceRecognitionService.AUDIO_SAMPLE_RATE, + sampleRate: WorkbenchVoiceRecognitionService.AUDIO_SAMPLING_RATE, latencyHint: 'interactive' }); From 196d0a8fe8db9e07dd06db6cdeab8878fc9936fc Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 18 Aug 2023 12:06:01 +0200 Subject: [PATCH 030/221] voice - log error in output --- src/vs/platform/voiceRecognition/node/voiceRecognitionService.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vs/platform/voiceRecognition/node/voiceRecognitionService.ts b/src/vs/platform/voiceRecognition/node/voiceRecognitionService.ts index a2a1d3218e9..71c72a1c814 100644 --- a/src/vs/platform/voiceRecognition/node/voiceRecognitionService.ts +++ b/src/vs/platform/voiceRecognition/node/voiceRecognitionService.ts @@ -39,6 +39,7 @@ export class VoiceRecognitionService implements IVoiceRecognitionService { const modulePath = process.env.VSCODE_VOICE_MODULE_PATH; if (!modulePath) { + this.logService.error(`[voice] transcribe(${channelData.length}): Voice recognition not yet supported`); throw new Error('Voice recognition not yet supported!'); } From 182970467566881d16ffce964188b0a5aed6741a Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Fri, 18 Aug 2023 12:17:35 +0200 Subject: [PATCH 031/221] cleaning the code --- .../src/configuration/configuration.ts | 6 ++++++ .../src/languageFeatures/diagnostics.ts | 17 +++-------------- .../src/typescriptServiceClient.ts | 2 +- 3 files changed, 10 insertions(+), 15 deletions(-) diff --git a/extensions/typescript-language-features/src/configuration/configuration.ts b/extensions/typescript-language-features/src/configuration/configuration.ts index cab1cf4c819..2650d015d88 100644 --- a/extensions/typescript-language-features/src/configuration/configuration.ts +++ b/extensions/typescript-language-features/src/configuration/configuration.ts @@ -112,6 +112,7 @@ export interface TypeScriptServiceConfiguration { readonly useSyntaxServer: SyntaxServerConfiguration; readonly webProjectWideIntellisenseEnabled: boolean; readonly webProjectWideIntellisenseSuppressSemanticErrors: boolean; + readonly enableDiagnosticsTelemetry: boolean; readonly enableProjectDiagnostics: boolean; readonly maxTsServerMemory: number; readonly enablePromptUseWorkspaceTsdk: boolean; @@ -144,6 +145,7 @@ export abstract class BaseServiceConfigurationProvider implements ServiceConfigu useSyntaxServer: this.readUseSyntaxServer(configuration), webProjectWideIntellisenseEnabled: this.readWebProjectWideIntellisenseEnable(configuration), webProjectWideIntellisenseSuppressSemanticErrors: this.readWebProjectWideIntellisenseSuppressSemanticErrors(configuration), + enableDiagnosticsTelemetry: this.readEnableDiagnosticsTelemetry(configuration), enableProjectDiagnostics: this.readEnableProjectDiagnostics(configuration), maxTsServerMemory: this.readMaxTsServerMemory(configuration), enablePromptUseWorkspaceTsdk: this.readEnablePromptUseWorkspaceTsdk(configuration), @@ -197,6 +199,10 @@ export abstract class BaseServiceConfigurationProvider implements ServiceConfigu return SyntaxServerConfiguration.Never; } + protected readEnableDiagnosticsTelemetry(configuration: vscode.WorkspaceConfiguration): boolean { + return configuration.get('typescript.enableDiagnosticsTelemetry', false); + } + protected readEnableProjectDiagnostics(configuration: vscode.WorkspaceConfiguration): boolean { return configuration.get('typescript.tsserver.experimental.enableProjectDiagnostics', false); } diff --git a/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts b/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts index 4331278c4ff..d3694cafdb1 100644 --- a/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts +++ b/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts @@ -10,7 +10,7 @@ import { Disposable } from '../utils/dispose'; import { ResourceMap } from '../utils/resourceMap'; import { TelemetryReporter } from '../logging/telemetry'; import { URI } from 'vscode-uri'; -import { diff } from 'semver'; +import { TypeScriptServiceConfiguration } from '../configuration/configuration'; function diagnosticsEquals(a: vscode.Diagnostic, b: vscode.Diagnostic): boolean { if (a === b) { @@ -151,18 +151,6 @@ class DiagnosticSettings { } } -/* -const diagnostics = this.getDiagnostics(document.uri); - const diagnoticCodes = diagnostics.reduce(function (result: number[], d: vscode.Diagnostic) { - const code = d.code; - if (typeof code === 'string' || typeof code === 'number') { - result.push(Number(code)); - } else if (code !== undefined) { - result.push(Number(code.value)); - } - return result; - }, []); - */ class DiagnosticsTelemetryManager extends Disposable { private readonly _timeOutDiagnosticMaps = new Map(); @@ -245,6 +233,7 @@ export class DiagnosticsManager extends Disposable { constructor( owner: string, + configuration: TypeScriptServiceConfiguration, telemetryReporter: TelemetryReporter, onCaseInsensitiveFileSystem: boolean ) { @@ -253,7 +242,7 @@ export class DiagnosticsManager extends Disposable { this._pendingUpdates = new ResourceMap(undefined, { onCaseInsensitiveFileSystem }); this._currentDiagnostics = this._register(vscode.languages.createDiagnosticCollection(owner)); - if (Math.random() * 1000 <= 1) { + if (Math.random() * 1000 <= 1 || configuration.enableDiagnosticsTelemetry) { this._register(new DiagnosticsTelemetryManager(telemetryReporter, this.getDiagnostics)); } } diff --git a/extensions/typescript-language-features/src/typescriptServiceClient.ts b/extensions/typescript-language-features/src/typescriptServiceClient.ts index c165f82db40..e00bed60b3f 100644 --- a/extensions/typescript-language-features/src/typescriptServiceClient.ts +++ b/extensions/typescript-language-features/src/typescriptServiceClient.ts @@ -212,7 +212,7 @@ export default class TypeScriptServiceClient extends Disposable implements IType } return this.apiVersion.fullVersionString; }); - this.diagnosticsManager = new DiagnosticsManager('typescript', this.telemetryReporter, onCaseInsenitiveFileSystem); + this.diagnosticsManager = new DiagnosticsManager('typescript', this._configuration, this.telemetryReporter, onCaseInsenitiveFileSystem); this.typescriptServerSpawner = new TypeScriptServerSpawner(this.versionProvider, this._versionManager, this.logDirectoryProvider, this.pluginPathsProvider, this.logger, this.telemetryReporter, this.tracer, this.processFactory); this._register(this.pluginManager.onDidUpdateConfig(update => { From 3e937b6a20022ee622ed53bf2786de6e3695f5d4 Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Fri, 18 Aug 2023 12:55:25 +0200 Subject: [PATCH 032/221] cleaning the code --- .../src/languageFeatures/diagnostics.ts | 31 ++++++++++++------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts b/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts index d3694cafdb1..cfd73512209 100644 --- a/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts +++ b/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts @@ -153,9 +153,9 @@ class DiagnosticSettings { class DiagnosticsTelemetryManager extends Disposable { - private readonly _timeOutDiagnosticMaps = new Map(); - private readonly _diagnosticsSnapshot = new Map(); private readonly _diagnosticCodesMap = new Map(); + private readonly _diagnosticTimeoutsMap = new Map(); + private readonly _diagnosticSnapshotsMap = new Map(); constructor( private readonly _telemetryReporter: TelemetryReporter, @@ -164,28 +164,37 @@ class DiagnosticsTelemetryManager extends Disposable { super(); this._register(vscode.workspace.onDidChangeTextDocument(e => { if (e.document.languageId === 'typescript') { - clearTimeout(this._timeOutDiagnosticMaps.get(e.document.uri)); - const timeOut = setTimeout(() => { this._updateDiagnosticCodes(e.document.uri); }, 5000); - this._timeOutDiagnosticMaps.set(e.document.uri, timeOut); + this._updateDiagnosticCodesAfterTimeout(e.document.uri, 10000); } })); this._register(vscode.workspace.onDidOpenTextDocument(e => { if (e.languageId === 'typescript') { - this._timeOutDiagnosticMaps.set(e.uri, undefined); + this._updateDiagnosticCodesAfterTimeout(e.uri, 10000); } })); this._register(vscode.workspace.onDidCloseTextDocument(e => { if (e.languageId === 'typescript') { - this._timeOutDiagnosticMaps.delete(e.uri); + this._diagnosticTimeoutsMap.delete(e.uri); } })); + const activeUri = vscode.window.activeTextEditor?.document.uri; + this._updateDiagnosticCodesAfterTimeout(activeUri, 10000); this._sendTelemetryEvent(); } + private _updateDiagnosticCodesAfterTimeout(uri: URI | undefined, timeoutInMs: number) { + if (!uri) { + return; + } + clearTimeout(this._diagnosticTimeoutsMap.get(uri)); + const timeout = setTimeout(() => { this._updateDiagnosticCodes(uri); }, timeoutInMs); + this._diagnosticTimeoutsMap.set(uri, timeout); + } + private _updateDiagnosticCodes(uri: URI) { - const previousDiagnostics = this._diagnosticsSnapshot.get(uri); + const previousDiagnostics = this._diagnosticSnapshotsMap.get(uri); const currentDiagnostics = this._getDiagnostics(uri); - this._diagnosticsSnapshot.set(uri, currentDiagnostics); + this._diagnosticSnapshotsMap.set(uri, currentDiagnostics); const diagnosticsDiff = currentDiagnostics.filter((diagnostic) => !previousDiagnostics?.some((previousDiagnostic) => JSON.stringify(diagnostic) === JSON.stringify(previousDiagnostic))); diagnosticsDiff.forEach((diagnostic) => { const code = diagnostic.code; @@ -219,7 +228,7 @@ class DiagnosticsTelemetryManager extends Disposable { }); } this._sendTelemetryEvent(); - }, 5 * 60 * 1000); + }, 5 * 60 * 1000); // 5 minutes } } @@ -243,7 +252,7 @@ export class DiagnosticsManager extends Disposable { this._currentDiagnostics = this._register(vscode.languages.createDiagnosticCollection(owner)); if (Math.random() * 1000 <= 1 || configuration.enableDiagnosticsTelemetry) { - this._register(new DiagnosticsTelemetryManager(telemetryReporter, this.getDiagnostics)); + this._register(new DiagnosticsTelemetryManager(telemetryReporter, this.getDiagnostics.bind(this))); } } From d56bd87a31ae8b268553e3b128278411d1279f1a Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Fri, 18 Aug 2023 14:35:17 +0200 Subject: [PATCH 033/221] using instead the vscode Uri instead of the entity from vscode-uri --- .../src/languageFeatures/diagnostics.ts | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts b/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts index cfd73512209..8897d6ac96a 100644 --- a/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts +++ b/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts @@ -9,7 +9,6 @@ import * as arrays from '../utils/arrays'; import { Disposable } from '../utils/dispose'; import { ResourceMap } from '../utils/resourceMap'; import { TelemetryReporter } from '../logging/telemetry'; -import { URI } from 'vscode-uri'; import { TypeScriptServiceConfiguration } from '../configuration/configuration'; function diagnosticsEquals(a: vscode.Diagnostic, b: vscode.Diagnostic): boolean { @@ -154,12 +153,12 @@ class DiagnosticSettings { class DiagnosticsTelemetryManager extends Disposable { private readonly _diagnosticCodesMap = new Map(); - private readonly _diagnosticTimeoutsMap = new Map(); - private readonly _diagnosticSnapshotsMap = new Map(); + private readonly _diagnosticTimeoutsMap = new Map(); + private readonly _diagnosticSnapshotsMap = new Map(); constructor( private readonly _telemetryReporter: TelemetryReporter, - private readonly _getDiagnostics: (uri: URI) => readonly vscode.Diagnostic[] + private readonly _getDiagnostics: (uri: vscode.Uri) => readonly vscode.Diagnostic[] ) { super(); this._register(vscode.workspace.onDidChangeTextDocument(e => { @@ -182,7 +181,7 @@ class DiagnosticsTelemetryManager extends Disposable { this._sendTelemetryEvent(); } - private _updateDiagnosticCodesAfterTimeout(uri: URI | undefined, timeoutInMs: number) { + private _updateDiagnosticCodesAfterTimeout(uri: vscode.Uri | undefined, timeoutInMs: number) { if (!uri) { return; } @@ -191,7 +190,7 @@ class DiagnosticsTelemetryManager extends Disposable { this._diagnosticTimeoutsMap.set(uri, timeout); } - private _updateDiagnosticCodes(uri: URI) { + private _updateDiagnosticCodes(uri: vscode.Uri) { const previousDiagnostics = this._diagnosticSnapshotsMap.get(uri); const currentDiagnostics = this._getDiagnostics(uri); this._diagnosticSnapshotsMap.set(uri, currentDiagnostics); From 1f86585b9bc07bd5e3544e72fe2f863be7b34fb9 Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Fri, 18 Aug 2023 14:37:30 +0200 Subject: [PATCH 034/221] remove the setting of 10000 for updating the diagnostics --- .../src/languageFeatures/diagnostics.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts b/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts index 8897d6ac96a..cb097121267 100644 --- a/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts +++ b/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts @@ -163,12 +163,12 @@ class DiagnosticsTelemetryManager extends Disposable { super(); this._register(vscode.workspace.onDidChangeTextDocument(e => { if (e.document.languageId === 'typescript') { - this._updateDiagnosticCodesAfterTimeout(e.document.uri, 10000); + this._updateDiagnosticCodesAfterTimeout(e.document.uri); } })); this._register(vscode.workspace.onDidOpenTextDocument(e => { if (e.languageId === 'typescript') { - this._updateDiagnosticCodesAfterTimeout(e.uri, 10000); + this._updateDiagnosticCodesAfterTimeout(e.uri); } })); this._register(vscode.workspace.onDidCloseTextDocument(e => { @@ -177,16 +177,16 @@ class DiagnosticsTelemetryManager extends Disposable { } })); const activeUri = vscode.window.activeTextEditor?.document.uri; - this._updateDiagnosticCodesAfterTimeout(activeUri, 10000); + this._updateDiagnosticCodesAfterTimeout(activeUri); this._sendTelemetryEvent(); } - private _updateDiagnosticCodesAfterTimeout(uri: vscode.Uri | undefined, timeoutInMs: number) { + private _updateDiagnosticCodesAfterTimeout(uri: vscode.Uri | undefined) { if (!uri) { return; } clearTimeout(this._diagnosticTimeoutsMap.get(uri)); - const timeout = setTimeout(() => { this._updateDiagnosticCodes(uri); }, timeoutInMs); + const timeout = setTimeout(() => { this._updateDiagnosticCodes(uri); }, 10000); this._diagnosticTimeoutsMap.set(uri, timeout); } From 03f09a238ce1a50d2e55207fd217b23281e29b04 Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Fri, 18 Aug 2023 14:40:14 +0200 Subject: [PATCH 035/221] adding a comment --- .../src/languageFeatures/diagnostics.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts b/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts index cb097121267..8ee7322975c 100644 --- a/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts +++ b/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts @@ -250,6 +250,7 @@ export class DiagnosticsManager extends Disposable { this._pendingUpdates = new ResourceMap(undefined, { onCaseInsensitiveFileSystem }); this._currentDiagnostics = this._register(vscode.languages.createDiagnosticCollection(owner)); + // Here we are selecting only 1 user out of 1000 to send telemetry diagnostics if (Math.random() * 1000 <= 1 || configuration.enableDiagnosticsTelemetry) { this._register(new DiagnosticsTelemetryManager(telemetryReporter, this.getDiagnostics.bind(this))); } From afcac53ae9f752804e39ced694a7d213c7d63b05 Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Fri, 18 Aug 2023 14:59:44 +0200 Subject: [PATCH 036/221] review comments --- .../src/languageFeatures/diagnostics.ts | 39 +++++++------------ 1 file changed, 14 insertions(+), 25 deletions(-) diff --git a/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts b/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts index 8ee7322975c..fb09cee0b04 100644 --- a/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts +++ b/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts @@ -153,8 +153,8 @@ class DiagnosticSettings { class DiagnosticsTelemetryManager extends Disposable { private readonly _diagnosticCodesMap = new Map(); - private readonly _diagnosticTimeoutsMap = new Map(); private readonly _diagnosticSnapshotsMap = new Map(); + private _timeout: NodeJS.Timeout | undefined; constructor( private readonly _telemetryReporter: TelemetryReporter, @@ -163,31 +163,21 @@ class DiagnosticsTelemetryManager extends Disposable { super(); this._register(vscode.workspace.onDidChangeTextDocument(e => { if (e.document.languageId === 'typescript') { - this._updateDiagnosticCodesAfterTimeout(e.document.uri); + this._updateDiagnosticCodesAfterTimeoutForUri(e.document.uri); } })); - this._register(vscode.workspace.onDidOpenTextDocument(e => { - if (e.languageId === 'typescript') { - this._updateDiagnosticCodesAfterTimeout(e.uri); - } - })); - this._register(vscode.workspace.onDidCloseTextDocument(e => { - if (e.languageId === 'typescript') { - this._diagnosticTimeoutsMap.delete(e.uri); - } - })); - const activeUri = vscode.window.activeTextEditor?.document.uri; - this._updateDiagnosticCodesAfterTimeout(activeUri); - this._sendTelemetryEvent(); + this._updateAllDiagnosticCodesAfterTimeout(); + this._registerTelemetryEventEmitter(); } - private _updateDiagnosticCodesAfterTimeout(uri: vscode.Uri | undefined) { - if (!uri) { - return; - } - clearTimeout(this._diagnosticTimeoutsMap.get(uri)); - const timeout = setTimeout(() => { this._updateDiagnosticCodes(uri); }, 10000); - this._diagnosticTimeoutsMap.set(uri, timeout); + private _updateAllDiagnosticCodesAfterTimeout() { + const uris = vscode.workspace.textDocuments.map(doc => doc.uri); + uris.forEach(uri => setTimeout(() => { this._updateDiagnosticCodes(uri); }, 10000)); + } + + private _updateDiagnosticCodesAfterTimeoutForUri(uri: vscode.Uri) { + clearTimeout(this._timeout); + this._timeout = setTimeout(() => { this._updateDiagnosticCodes(uri); }, 10000); } private _updateDiagnosticCodes(uri: vscode.Uri) { @@ -205,8 +195,8 @@ class DiagnosticsTelemetryManager extends Disposable { }); } - private _sendTelemetryEvent() { - setTimeout(() => { + private _registerTelemetryEventEmitter() { + setInterval(() => { if (this._diagnosticCodesMap.size > 0) { let diagnosticCodes = ''; this._diagnosticCodesMap.forEach((value, key) => { @@ -226,7 +216,6 @@ class DiagnosticsTelemetryManager extends Disposable { diagnoticCodes: diagnosticCodes }); } - this._sendTelemetryEvent(); }, 5 * 60 * 1000); // 5 minutes } } From b0d44b6b045b990bd75112982792fc25cfd9e6fd Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 18 Aug 2023 15:42:27 +0200 Subject: [PATCH 037/221] voice - wire into chat widget as action --- src/vs/workbench/contrib/chat/browser/chat.ts | 2 + .../contrib/chat/browser/chatInputPart.ts | 2 +- .../contrib/chat/browser/chatWidget.ts | 9 ++ .../actions/chatVoiceInputActions.ts | 140 ++++++++++++++++++ .../electron-sandbox/chat.contribution.ts | 48 +----- 5 files changed, 154 insertions(+), 47 deletions(-) create mode 100644 src/vs/workbench/contrib/chat/electron-sandbox/actions/chatVoiceInputActions.ts diff --git a/src/vs/workbench/contrib/chat/browser/chat.ts b/src/vs/workbench/contrib/chat/browser/chat.ts index 59e1f4181ef..3ff45ac4f9c 100644 --- a/src/vs/workbench/contrib/chat/browser/chat.ts +++ b/src/vs/workbench/contrib/chat/browser/chat.ts @@ -70,6 +70,7 @@ export type IChatWidgetViewContext = IChatViewViewContext | IChatResourceViewCon export interface IChatWidget { readonly onDidChangeViewModel: Event; + readonly onDidAcceptInput: Event; readonly viewContext: IChatWidgetViewContext; readonly viewModel: IChatViewModel | undefined; readonly inputEditor: ICodeEditor; @@ -79,6 +80,7 @@ export interface IChatWidget { focus(item: ChatTreeItem): void; moveFocus(item: ChatTreeItem, type: 'next' | 'previous'): void; getFocus(): ChatTreeItem | undefined; + updateInput(query?: string): void; acceptInput(query?: string): void; focusLastMessage(): void; focusInput(): void; diff --git a/src/vs/workbench/contrib/chat/browser/chatInputPart.ts b/src/vs/workbench/contrib/chat/browser/chatInputPart.ts index 6dce4e1d7d1..2b05567c7b1 100644 --- a/src/vs/workbench/contrib/chat/browser/chatInputPart.ts +++ b/src/vs/workbench/contrib/chat/browser/chatInputPart.ts @@ -138,7 +138,7 @@ export class ChatInputPart extends Disposable implements IHistoryNavigationWidge this.setHistoryNavigationEnablement(true); } - private setValue(value: string): void { + setValue(value: string): void { this.inputEditor.setValue(value); // always leave cursor at the end this.inputEditor.setPosition({ lineNumber: 1, column: value.length + 1 }); diff --git a/src/vs/workbench/contrib/chat/browser/chatWidget.ts b/src/vs/workbench/contrib/chat/browser/chatWidget.ts index 9f623e3381e..aca5a1d961f 100644 --- a/src/vs/workbench/contrib/chat/browser/chatWidget.ts +++ b/src/vs/workbench/contrib/chat/browser/chatWidget.ts @@ -61,6 +61,9 @@ export class ChatWidget extends Disposable implements IChatWidget { private _onDidClear = this._register(new Emitter()); readonly onDidClear = this._onDidClear.event; + private _onDidAcceptInput = this._register(new Emitter()); + readonly onDidAcceptInput = this._onDidAcceptInput.event; + private tree!: WorkbenchObjectTree; private renderer!: ChatListItemRenderer; @@ -432,8 +435,14 @@ export class ChatWidget extends Disposable implements IChatWidget { this.tree.domFocus(); } + updateInput(value = ''): void { + this.inputPart.setValue(value); + } + async acceptInput(query?: string | IChatReplyFollowup): Promise { if (this.viewModel) { + this._onDidAcceptInput.fire(); + const editorValue = this.inputPart.inputEditor.getValue(); this._chatAccessibilityService.acceptRequest(); const input = query ?? editorValue; diff --git a/src/vs/workbench/contrib/chat/electron-sandbox/actions/chatVoiceInputActions.ts b/src/vs/workbench/contrib/chat/electron-sandbox/actions/chatVoiceInputActions.ts new file mode 100644 index 00000000000..88987d229f8 --- /dev/null +++ b/src/vs/workbench/contrib/chat/electron-sandbox/actions/chatVoiceInputActions.ts @@ -0,0 +1,140 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { CancellationTokenSource } from 'vs/base/common/cancellation'; +import { Codicon } from 'vs/base/common/codicons'; +import { DisposableStore, toDisposable } from 'vs/base/common/lifecycle'; +import { ServicesAccessor } from 'vs/editor/browser/editorExtensions'; +import { localize } from 'vs/nls'; +import { Action2, MenuId, registerAction2 } from 'vs/platform/actions/common/actions'; +import { ContextKeyExpr, IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey'; +import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { IChatWidget } from 'vs/workbench/contrib/chat/browser/chat'; +import { CONTEXT_CHAT_REQUEST_IN_PROGRESS } from 'vs/workbench/contrib/chat/common/chatContextKeys'; +import { IWorkbenchVoiceRecognitionService } from 'vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService'; + +const CONTEXT_CHAT_VOICE_INPUT_IN_PROGRESS = new RawContextKey('chatVoiceInputInProgress', false, { type: 'boolean', description: localize('interactiveSessionVoiceInputInProgress', "True when there is voice input for chat in progress.") }); + +interface IChatVoiceInputActionContext { + readonly widget: IChatWidget; + readonly inputValue?: string; +} + +function isVoiceInputActionContext(thing: unknown): thing is IChatVoiceInputActionContext { + return typeof thing === 'object' && thing !== null && 'widget' in thing; +} + +class ChatVoiceInputSession { + + private static instance: ChatVoiceInputSession | undefined = undefined; + static getInstance(instantiationService: IInstantiationService): ChatVoiceInputSession { + if (!ChatVoiceInputSession.instance) { + ChatVoiceInputSession.instance = instantiationService.createInstance(ChatVoiceInputSession); + } + + return ChatVoiceInputSession.instance; + } + + private chatVoiceInputInProgressKey = CONTEXT_CHAT_VOICE_INPUT_IN_PROGRESS.bindTo(this.contextKeyService); + private currentChatVoiceInputSession: DisposableStore | undefined = undefined; + + constructor( + @IContextKeyService private readonly contextKeyService: IContextKeyService, + @IWorkbenchVoiceRecognitionService private readonly voiceRecognitionService: IWorkbenchVoiceRecognitionService + ) { } + + start(context: IChatVoiceInputActionContext): void { + this.stop(); + + this.chatVoiceInputInProgressKey.set(true); + this.currentChatVoiceInputSession = new DisposableStore(); + + const cts = new CancellationTokenSource(); + this.currentChatVoiceInputSession.add(toDisposable(() => cts.dispose(true))); + + context.widget.focusInput(); + + this.currentChatVoiceInputSession.add(this.voiceRecognitionService.transcribe(cts.token)(text => { + if (text) { + context.widget.updateInput(text); + } + })); + + this.currentChatVoiceInputSession.add(context.widget.onDidAcceptInput(() => { + this.stop(); + })); + } + + stop(): void { + if (!this.currentChatVoiceInputSession) { + return; + } + + this.currentChatVoiceInputSession.dispose(); + this.currentChatVoiceInputSession = undefined; + + this.chatVoiceInputInProgressKey.set(false); + } +} + +class StartChatVoiceInputAction extends Action2 { + static readonly ID = 'workbench.action.chat.startVoiceInput'; + + constructor() { + super({ + id: StartChatVoiceInputAction.ID, + title: { + value: localize('interactive.voiceInput.label', "Start Voice Input"), + original: 'Start Voice Input' + }, + icon: Codicon.record, + menu: { + id: MenuId.ChatExecute, + when: ContextKeyExpr.and(CONTEXT_CHAT_VOICE_INPUT_IN_PROGRESS.negate(), CONTEXT_CHAT_REQUEST_IN_PROGRESS.negate()), + group: 'navigation', + order: -1 + } + }); + } + + run(accessor: ServicesAccessor, ...args: any[]) { + const context = args[0]; + if (!isVoiceInputActionContext(context)) { + return; + } + + ChatVoiceInputSession.getInstance(accessor.get(IInstantiationService)).start(context); + } +} + +class StopChatVoiceInputAction extends Action2 { + static readonly ID = 'workbench.action.chat.stopVoiceInput'; + + constructor() { + super({ + id: StopChatVoiceInputAction.ID, + title: { + value: localize('interactive.stopVoiceInput.label', "Stop Voice Input"), + original: 'Stop Voice Input' + }, + icon: Codicon.stop, + menu: { + id: MenuId.ChatExecute, + when: CONTEXT_CHAT_VOICE_INPUT_IN_PROGRESS, + group: 'navigation', + order: -1 + } + }); + } + + run(accessor: ServicesAccessor) { + ChatVoiceInputSession.getInstance(accessor.get(IInstantiationService)).stop(); + } +} + +export function registerChatVoiceInputActions() { + registerAction2(StartChatVoiceInputAction); + registerAction2(StopChatVoiceInputAction); +} diff --git a/src/vs/workbench/contrib/chat/electron-sandbox/chat.contribution.ts b/src/vs/workbench/contrib/chat/electron-sandbox/chat.contribution.ts index 45bb21c29ef..5d49a2d0625 100644 --- a/src/vs/workbench/contrib/chat/electron-sandbox/chat.contribution.ts +++ b/src/vs/workbench/contrib/chat/electron-sandbox/chat.contribution.ts @@ -3,50 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { toAction } from 'vs/base/common/actions'; -import { CancellationTokenSource } from 'vs/base/common/cancellation'; -import { DisposableStore, toDisposable } from 'vs/base/common/lifecycle'; -import { CommandsRegistry } from 'vs/platform/commands/common/commands'; -import { INotificationService, NotificationPriority, Severity } from 'vs/platform/notification/common/notification'; -import { IWorkbenchVoiceRecognitionService } from 'vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService'; +import { registerChatVoiceInputActions } from 'vs/workbench/contrib/chat/electron-sandbox/actions/chatVoiceInputActions'; -let activeVoiceTranscription: DisposableStore | undefined; - -function stopVoiceTranscription() { - activeVoiceTranscription?.dispose(); - activeVoiceTranscription = undefined; -} - -CommandsRegistry.registerCommand('workbench.action.toggleVoiceTranscription', async services => { - if (activeVoiceTranscription) { - stopVoiceTranscription(); - } else { - const voiceRecognitionService = services.get(IWorkbenchVoiceRecognitionService); - const notificationService = services.get(INotificationService); - - activeVoiceTranscription = new DisposableStore(); - - const cts = new CancellationTokenSource(); - activeVoiceTranscription.add(toDisposable(() => cts.dispose(true))); - - const voiceTranscriptionNotification = notificationService.notify({ - severity: Severity.Info, - priority: NotificationPriority.URGENT, - sticky: true, - message: 'Listening...', - actions: { - primary: [ - toAction({ id: 'stopVoiceTranscription', label: 'Stop', run: () => stopVoiceTranscription() }) - ] - } - }); - - activeVoiceTranscription.add(toDisposable(() => voiceTranscriptionNotification.close())); - - activeVoiceTranscription.add(voiceRecognitionService.transcribe(cts.token)(text => { - if (text) { - voiceTranscriptionNotification.updateMessage(text); - } - })); - } -}); +registerChatVoiceInputActions(); From aa254f84f90816dacdb1d1d2ec48ede7ffb88c63 Mon Sep 17 00:00:00 2001 From: meganrogge Date: Fri, 18 Aug 2023 09:15:32 -0700 Subject: [PATCH 038/221] handle escape while in toolbar --- .../accessibility/browser/accessibleView.ts | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts b/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts index 71fcfb7a5a3..953d7284097 100644 --- a/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts +++ b/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts @@ -38,6 +38,7 @@ import { IAction } from 'vs/base/common/actions'; import { createAndFillInActionBarActions } from 'vs/platform/actions/browser/menuEntryActionViewItem'; import { Codicon } from 'vs/base/common/codicons'; import { ThemeIcon } from 'vs/base/common/themables'; +import { addDisposableListener } from 'vs/base/browser/dom'; const enum DIMENSIONS { MAX_WIDTH = 600 @@ -346,15 +347,18 @@ class AccessibleView extends Disposable { }); this._updateToolbar(provider.actions, provider.options.type); + const handleEscape = (e: KeyboardEvent | IKeyboardEvent): void => { + e.stopPropagation(); + this._contextViewService.hideContextView(); + this._updateContextKeys(provider, false); + // HACK: Delay to allow the context view to hide #186514 + setTimeout(() => provider.onClose(), 100); + }; const disposableStore = new DisposableStore(); disposableStore.add(this._editorWidget.onKeyUp((e) => provider.onKeyDown?.(e))); disposableStore.add(this._editorWidget.onKeyDown((e) => { if (e.keyCode === KeyCode.Escape) { - e.stopPropagation(); - this._contextViewService.hideContextView(); - this._updateContextKeys(provider, false); - // HACK: Delay to allow the context view to hide #186514 - setTimeout(() => provider.onClose(), 100); + handleEscape(e); } else if (e.keyCode === KeyCode.KeyH && provider.options.readMoreUrl) { const url: string = provider.options.readMoreUrl!; alert(AccessibilityHelpNLS.openingDocs); @@ -363,6 +367,11 @@ class AccessibleView extends Disposable { e.stopPropagation(); } })); + disposableStore.add(addDisposableListener(this._toolbar.getElement(), 'keydown', (e: KeyboardEvent) => { + if (e.key === 'Escape') { + handleEscape(e); + } + })); disposableStore.add(this._editorWidget.onDidBlurEditorWidget(() => { if (document.activeElement !== this._toolbar.getElement()) { this._contextViewService.hideContextView(); From c6ac21f37b6521c7bf27b7782005182a30781910 Mon Sep 17 00:00:00 2001 From: meganrogge Date: Fri, 18 Aug 2023 09:16:28 -0700 Subject: [PATCH 039/221] appropriately rename property --- .../workbench/contrib/accessibility/browser/accessibleView.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts b/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts index 953d7284097..71e366bfcce 100644 --- a/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts +++ b/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts @@ -54,7 +54,7 @@ export interface IAccessibleContentProvider { actions?: IAction[]; provideContent(): string; onClose(): void; - onKeyDown?(e: IKeyboardEvent): void; + onKeyUp?(e: IKeyboardEvent): void; previous?(): void; next?(): void; /** @@ -355,7 +355,7 @@ class AccessibleView extends Disposable { setTimeout(() => provider.onClose(), 100); }; const disposableStore = new DisposableStore(); - disposableStore.add(this._editorWidget.onKeyUp((e) => provider.onKeyDown?.(e))); + disposableStore.add(this._editorWidget.onKeyUp((e) => provider.onKeyUp?.(e))); disposableStore.add(this._editorWidget.onKeyDown((e) => { if (e.keyCode === KeyCode.Escape) { handleEscape(e); From 810611318eb169b5dfad250408d33b1805220a0b Mon Sep 17 00:00:00 2001 From: Megan Rogge Date: Fri, 18 Aug 2023 12:12:40 -0700 Subject: [PATCH 040/221] Update src/vs/workbench/contrib/accessibility/browser/accessibleView.ts Co-authored-by: Joyce Er --- .../contrib/accessibility/browser/accessibleView.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts b/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts index 71e366bfcce..8d7c443f9e6 100644 --- a/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts +++ b/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts @@ -367,8 +367,9 @@ class AccessibleView extends Disposable { e.stopPropagation(); } })); - disposableStore.add(addDisposableListener(this._toolbar.getElement(), 'keydown', (e: KeyboardEvent) => { - if (e.key === 'Escape') { + disposableStore.add(addDisposableListener(this._toolbar.getElement(), DOM.EventType.KEY_DOWN, (e: KeyboardEvent) => { + const keyboardEvent = new StandardKeyboardEvent(e); + if (keyboardEvent.equals(KeyCode.Escape)) { handleEscape(e); } })); From 66eb90b07ce470642e7f5ac8439323127581740f Mon Sep 17 00:00:00 2001 From: Joyce Er Date: Fri, 18 Aug 2023 13:17:10 -0700 Subject: [PATCH 041/221] Add missing imports --- .../contrib/accessibility/browser/accessibleView.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts b/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts index 8d7c443f9e6..3ae64e09409 100644 --- a/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts +++ b/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts @@ -38,7 +38,8 @@ import { IAction } from 'vs/base/common/actions'; import { createAndFillInActionBarActions } from 'vs/platform/actions/browser/menuEntryActionViewItem'; import { Codicon } from 'vs/base/common/codicons'; import { ThemeIcon } from 'vs/base/common/themables'; -import { addDisposableListener } from 'vs/base/browser/dom'; +import { addDisposableListener, EventType } from 'vs/base/browser/dom'; +import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; const enum DIMENSIONS { MAX_WIDTH = 600 @@ -367,9 +368,9 @@ class AccessibleView extends Disposable { e.stopPropagation(); } })); - disposableStore.add(addDisposableListener(this._toolbar.getElement(), DOM.EventType.KEY_DOWN, (e: KeyboardEvent) => { + disposableStore.add(addDisposableListener(this._toolbar.getElement(), EventType.KEY_DOWN, (e: KeyboardEvent) => { const keyboardEvent = new StandardKeyboardEvent(e); - if (keyboardEvent.equals(KeyCode.Escape)) { + if (keyboardEvent.equals(KeyCode.Escape)) { handleEscape(e); } })); From 12746bae34a36f37452d8188902cb3b01491f80b Mon Sep 17 00:00:00 2001 From: Joyce Er Date: Fri, 18 Aug 2023 14:11:00 -0700 Subject: [PATCH 042/221] Fix import --- .../workbench/contrib/accessibility/browser/accessibleView.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts b/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts index 3ae64e09409..8acbdb7b870 100644 --- a/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts +++ b/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent'; +import { IKeyboardEvent, StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { ActionsOrientation } from 'vs/base/browser/ui/actionbar/actionbar'; import { alert } from 'vs/base/browser/ui/aria/aria'; import { KeyCode } from 'vs/base/common/keyCodes'; @@ -39,7 +39,6 @@ import { createAndFillInActionBarActions } from 'vs/platform/actions/browser/men import { Codicon } from 'vs/base/common/codicons'; import { ThemeIcon } from 'vs/base/common/themables'; import { addDisposableListener, EventType } from 'vs/base/browser/dom'; -import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; const enum DIMENSIONS { MAX_WIDTH = 600 From 4fb3cd66f56b1da667510da340b996836547959c Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Sat, 19 Aug 2023 11:32:17 +0200 Subject: [PATCH 043/221] voice - better actions and icons --- .../contrib/chat/browser/chatInputPart.ts | 16 +++++++++------- .../actions/chatVoiceInputActions.ts | 8 ++++---- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/vs/workbench/contrib/chat/browser/chatInputPart.ts b/src/vs/workbench/contrib/chat/browser/chatInputPart.ts index 2b05567c7b1..d0982610acd 100644 --- a/src/vs/workbench/contrib/chat/browser/chatInputPart.ts +++ b/src/vs/workbench/contrib/chat/browser/chatInputPart.ts @@ -40,7 +40,7 @@ const $ = dom.$; const INPUT_EDITOR_MAX_HEIGHT = 250; export class ChatInputPart extends Disposable implements IHistoryNavigationWidget { - public static readonly INPUT_SCHEME = 'chatSessionInput'; + static readonly INPUT_SCHEME = 'chatSessionInput'; private static _counter = 0; private _onDidChangeHeight = this._register(new Emitter()); @@ -64,7 +64,9 @@ export class ChatInputPart extends Disposable implements IHistoryNavigationWidge private _inputEditor!: CodeEditorWidget; private _inputEditorElement!: HTMLElement; - public get inputEditor() { + private toolbar!: MenuWorkbenchToolBar; + + get inputEditor() { return this._inputEditor; } @@ -74,7 +76,7 @@ export class ChatInputPart extends Disposable implements IHistoryNavigationWidge private inputEditorHasText: IContextKey; private providerId: string | undefined; - public readonly inputUri = URI.parse(`${ChatInputPart.INPUT_SCHEME}:input-${ChatInputPart._counter++}`); + readonly inputUri = URI.parse(`${ChatInputPart.INPUT_SCHEME}:input-${ChatInputPart._counter++}`); constructor( // private readonly editorOptions: ChatEditorOptions, // TODO this should be used @@ -233,13 +235,13 @@ export class ChatInputPart extends Disposable implements IHistoryNavigationWidge this._onDidBlur.fire(); })); - const toolbar = this._register(this.instantiationService.createInstance(MenuWorkbenchToolBar, inputContainer, MenuId.ChatExecute, { + this.toolbar = this._register(this.instantiationService.createInstance(MenuWorkbenchToolBar, inputContainer, MenuId.ChatExecute, { menuOptions: { shouldForwardArgs: true } })); - toolbar.getElement().classList.add('interactive-execute-toolbar'); - toolbar.context = { widget }; + this.toolbar.getElement().classList.add('interactive-execute-toolbar'); + this.toolbar.context = { widget }; if (this.options.renderStyle === 'compact') { const toolbarSide = this._register(this.instantiationService.createInstance(MenuWorkbenchToolBar, inputAndSideToolbar, MenuId.ChatInputSide, { @@ -290,7 +292,7 @@ export class ChatInputPart extends Disposable implements IHistoryNavigationWidge const editorBorder = 2; const editorPadding = 8; - const executeToolbarWidth = 25; + const executeToolbarWidth = this.toolbar.getItemsWidth(); const sideToolbarWidth = this.options.renderStyle === 'compact' ? 20 : 0; const initialEditorScrollWidth = this._inputEditor.getScrollWidth(); diff --git a/src/vs/workbench/contrib/chat/electron-sandbox/actions/chatVoiceInputActions.ts b/src/vs/workbench/contrib/chat/electron-sandbox/actions/chatVoiceInputActions.ts index 88987d229f8..4963c2dce0f 100644 --- a/src/vs/workbench/contrib/chat/electron-sandbox/actions/chatVoiceInputActions.ts +++ b/src/vs/workbench/contrib/chat/electron-sandbox/actions/chatVoiceInputActions.ts @@ -9,10 +9,10 @@ import { DisposableStore, toDisposable } from 'vs/base/common/lifecycle'; import { ServicesAccessor } from 'vs/editor/browser/editorExtensions'; import { localize } from 'vs/nls'; import { Action2, MenuId, registerAction2 } from 'vs/platform/actions/common/actions'; -import { ContextKeyExpr, IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey'; +import { IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { spinningLoading } from 'vs/platform/theme/common/iconRegistry'; import { IChatWidget } from 'vs/workbench/contrib/chat/browser/chat'; -import { CONTEXT_CHAT_REQUEST_IN_PROGRESS } from 'vs/workbench/contrib/chat/common/chatContextKeys'; import { IWorkbenchVoiceRecognitionService } from 'vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService'; const CONTEXT_CHAT_VOICE_INPUT_IN_PROGRESS = new RawContextKey('chatVoiceInputInProgress', false, { type: 'boolean', description: localize('interactiveSessionVoiceInputInProgress', "True when there is voice input for chat in progress.") }); @@ -92,7 +92,7 @@ class StartChatVoiceInputAction extends Action2 { icon: Codicon.record, menu: { id: MenuId.ChatExecute, - when: ContextKeyExpr.and(CONTEXT_CHAT_VOICE_INPUT_IN_PROGRESS.negate(), CONTEXT_CHAT_REQUEST_IN_PROGRESS.negate()), + when: CONTEXT_CHAT_VOICE_INPUT_IN_PROGRESS.negate(), group: 'navigation', order: -1 } @@ -119,7 +119,7 @@ class StopChatVoiceInputAction extends Action2 { value: localize('interactive.stopVoiceInput.label', "Stop Voice Input"), original: 'Stop Voice Input' }, - icon: Codicon.stop, + icon: spinningLoading, menu: { id: MenuId.ChatExecute, when: CONTEXT_CHAT_VOICE_INPUT_IN_PROGRESS, From d91e1a8ba3be4dad18dc8f3a3de62638f4347be8 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Sat, 19 Aug 2023 11:47:26 +0200 Subject: [PATCH 044/221] voice - indicate when ready to record --- .../actions/chatVoiceInputActions.ts | 21 +++++++++++--- .../workbenchVoiceRecognitionService.ts | 29 ++++++++++++------- 2 files changed, 36 insertions(+), 14 deletions(-) diff --git a/src/vs/workbench/contrib/chat/electron-sandbox/actions/chatVoiceInputActions.ts b/src/vs/workbench/contrib/chat/electron-sandbox/actions/chatVoiceInputActions.ts index 4963c2dce0f..ed0dc175175 100644 --- a/src/vs/workbench/contrib/chat/electron-sandbox/actions/chatVoiceInputActions.ts +++ b/src/vs/workbench/contrib/chat/electron-sandbox/actions/chatVoiceInputActions.ts @@ -15,7 +15,8 @@ import { spinningLoading } from 'vs/platform/theme/common/iconRegistry'; import { IChatWidget } from 'vs/workbench/contrib/chat/browser/chat'; import { IWorkbenchVoiceRecognitionService } from 'vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService'; -const CONTEXT_CHAT_VOICE_INPUT_IN_PROGRESS = new RawContextKey('chatVoiceInputInProgress', false, { type: 'boolean', description: localize('interactiveSessionVoiceInputInProgress', "True when there is voice input for chat in progress.") }); +const CONTEXT_CHAT_VOICE_INPUT_GETTING_READY = new RawContextKey('chatVoiceInputGettingReady', false, { type: 'boolean', description: localize('chatVoiceInputGettingReady', "True when there is voice input for chat getting ready.") }); +const CONTEXT_CHAT_VOICE_INPUT_IN_PROGRESS = new RawContextKey('chatVoiceInputInProgress', false, { type: 'boolean', description: localize('chatVoiceInputInProgress', "True when there is voice input for chat in progress.") }); interface IChatVoiceInputActionContext { readonly widget: IChatWidget; @@ -38,6 +39,8 @@ class ChatVoiceInputSession { } private chatVoiceInputInProgressKey = CONTEXT_CHAT_VOICE_INPUT_IN_PROGRESS.bindTo(this.contextKeyService); + private chatVoiceInputGettingReadyKey = CONTEXT_CHAT_VOICE_INPUT_GETTING_READY.bindTo(this.contextKeyService); + private currentChatVoiceInputSession: DisposableStore | undefined = undefined; constructor( @@ -45,10 +48,10 @@ class ChatVoiceInputSession { @IWorkbenchVoiceRecognitionService private readonly voiceRecognitionService: IWorkbenchVoiceRecognitionService ) { } - start(context: IChatVoiceInputActionContext): void { + async start(context: IChatVoiceInputActionContext): Promise { this.stop(); - this.chatVoiceInputInProgressKey.set(true); + this.chatVoiceInputGettingReadyKey.set(true); this.currentChatVoiceInputSession = new DisposableStore(); const cts = new CancellationTokenSource(); @@ -56,7 +59,15 @@ class ChatVoiceInputSession { context.widget.focusInput(); - this.currentChatVoiceInputSession.add(this.voiceRecognitionService.transcribe(cts.token)(text => { + const onDidTranscribe = await this.voiceRecognitionService.transcribe(cts.token); + if (cts.token.isCancellationRequested) { + return; + } + + this.chatVoiceInputGettingReadyKey.set(false); + this.chatVoiceInputInProgressKey.set(true); + + this.currentChatVoiceInputSession.add(onDidTranscribe(text => { if (text) { context.widget.updateInput(text); } @@ -75,6 +86,7 @@ class ChatVoiceInputSession { this.currentChatVoiceInputSession.dispose(); this.currentChatVoiceInputSession = undefined; + this.chatVoiceInputGettingReadyKey.set(false); this.chatVoiceInputInProgressKey.set(false); } } @@ -90,6 +102,7 @@ class StartChatVoiceInputAction extends Action2 { original: 'Start Voice Input' }, icon: Codicon.record, + precondition: CONTEXT_CHAT_VOICE_INPUT_GETTING_READY.negate(), menu: { id: MenuId.ChatExecute, when: CONTEXT_CHAT_VOICE_INPUT_IN_PROGRESS.negate(), diff --git a/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts b/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts index e2e94971c3a..cc159e4f06b 100644 --- a/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts +++ b/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts @@ -25,7 +25,7 @@ export interface IWorkbenchVoiceRecognitionService { * @param cancellation a cancellation token to stop transcribing and * listening to the microphone. */ - transcribe(cancellation: CancellationToken): Event; + transcribe(cancellation: CancellationToken): Promise>; } class VoiceTranscriptionWorkletNode extends AudioWorkletNode { @@ -76,16 +76,19 @@ export class WorkbenchVoiceRecognitionService implements IWorkbenchVoiceRecognit @ISharedProcessService private readonly sharedProcessService: ISharedProcessService ) { } - transcribe(cancellation: CancellationToken): Event { + async transcribe(cancellation: CancellationToken): Promise> { const onDidTranscribe = new Emitter(); cancellation.onCancellationRequested(() => onDidTranscribe.dispose()); - this.doTranscribe(onDidTranscribe, cancellation); + await this.doTranscribe(onDidTranscribe, cancellation); return onDidTranscribe.event; } - private doTranscribe(onDidTranscribe: Emitter, token: CancellationToken): void { + private doTranscribe(onDidTranscribe: Emitter, token: CancellationToken): Promise { + const recordingReady = new DeferredPromise(); + token.onCancellationRequested(() => recordingReady.complete()); + this.progressService.withProgress({ location: ProgressLocation.Window, title: localize('voiceTranscription', "Voice Transcription"), @@ -116,13 +119,16 @@ export class WorkbenchVoiceRecognitionService implements IWorkbenchVoiceRecognit const microphoneSource = audioContext.createMediaStreamSource(microphoneDevice); token.onCancellationRequested(() => { - for (const track of microphoneDevice.getTracks()) { - track.stop(); - } + try { + for (const track of microphoneDevice.getTracks()) { + track.stop(); + } - microphoneSource.disconnect(); - audioContext.close(); - recordingDone.complete(); + microphoneSource.disconnect(); + audioContext.close(); + } finally { + recordingDone.complete(); + } }); await audioContext.audioWorklet.addModule(FileAccess.asBrowserUri('vs/workbench/services/voiceRecognition/electron-sandbox/voiceTranscriptionWorklet.js').toString(true)); @@ -144,9 +150,12 @@ export class WorkbenchVoiceRecognitionService implements IWorkbenchVoiceRecognit microphoneSource.connect(voiceTranscriptionTarget); progress.report({ message: localize('voiceTranscriptionRecording', "Recording from microphone...") }); + recordingReady.complete(); return recordingDone.p; }); + + return recordingReady.p; } } From c1715502dd926328198cca7b386cc8fdf34e836f Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Sun, 20 Aug 2023 08:15:14 +0200 Subject: [PATCH 045/221] voice - auto accept input after a while --- .../actions/chatVoiceInputActions.ts | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/chat/electron-sandbox/actions/chatVoiceInputActions.ts b/src/vs/workbench/contrib/chat/electron-sandbox/actions/chatVoiceInputActions.ts index ed0dc175175..48e4c3b3f7d 100644 --- a/src/vs/workbench/contrib/chat/electron-sandbox/actions/chatVoiceInputActions.ts +++ b/src/vs/workbench/contrib/chat/electron-sandbox/actions/chatVoiceInputActions.ts @@ -67,9 +67,23 @@ class ChatVoiceInputSession { this.chatVoiceInputGettingReadyKey.set(false); this.chatVoiceInputInProgressKey.set(true); + let lastText: string | undefined = undefined; + let lastTextEqualCount = 0; + this.currentChatVoiceInputSession.add(onDidTranscribe(text => { if (text) { - context.widget.updateInput(text); + if (lastText === text) { + lastTextEqualCount++; + + if (lastTextEqualCount >= 2) { + context.widget.acceptInput(); + } + } else { + lastTextEqualCount = 0; + lastText = text; + + context.widget.updateInput(text); + } } })); From 1f515f71cff8fb13f86e25a2175dbe33d44fffe3 Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Mon, 21 Aug 2023 11:38:31 +0200 Subject: [PATCH 046/221] setting z-index to the z-index of the content hover --- .../browser/standaloneColorPickerWidget.ts | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/vs/editor/contrib/colorPicker/browser/standaloneColorPickerWidget.ts b/src/vs/editor/contrib/colorPicker/browser/standaloneColorPickerWidget.ts index 6d874e71d4b..a6ef1b75116 100644 --- a/src/vs/editor/contrib/colorPicker/browser/standaloneColorPickerWidget.ts +++ b/src/vs/editor/contrib/colorPicker/browser/standaloneColorPickerWidget.ts @@ -87,11 +87,10 @@ export class StandaloneColorPickerWidget extends Disposable implements IContentW static readonly ID = 'editor.contrib.standaloneColorPickerWidget'; readonly allowEditorOverflow = true; - private body: HTMLElement = document.createElement('div'); - private readonly _position: Position | undefined = undefined; private readonly _standaloneColorPickerParticipant: StandaloneColorPickerParticipant; + private _body: HTMLElement = document.createElement('div'); private _colorHover: StandaloneColorPickerHover | null = null; private _selectionSetInEditor: boolean = false; @@ -120,7 +119,7 @@ export class StandaloneColorPickerWidget extends Disposable implements IContentW endLineNumber: editorSelection.endLineNumber, endColumn: editorSelection.endColumn } : { startLineNumber: 0, endLineNumber: 0, endColumn: 0, startColumn: 0 }; - const focusTracker = this._register(dom.trackFocus(this.body)); + const focusTracker = this._register(dom.trackFocus(this._body)); this._register(focusTracker.onDidBlur(_ => { this.hide(); })); @@ -146,6 +145,7 @@ export class StandaloneColorPickerWidget extends Disposable implements IContentW this._render(result.value, result.foundInEditor); })); this._start(selection); + this._body.style.zIndex = '50'; this._editor.addContentWidget(this); } @@ -160,7 +160,7 @@ export class StandaloneColorPickerWidget extends Disposable implements IContentW } public getDomNode(): HTMLElement { - return this.body; + return this._body; } public getPosition(): IContentWidgetPosition | null { @@ -186,7 +186,7 @@ export class StandaloneColorPickerWidget extends Disposable implements IContentW public focus(): void { this._standaloneColorPickerFocused.set(true); - this.body.focus(); + this._body.focus(); } private async _start(selection: IRange) { @@ -230,11 +230,11 @@ export class StandaloneColorPickerWidget extends Disposable implements IContentW if (colorPickerWidget === undefined) { return; } - this.body.classList.add('standalone-colorpicker-body'); - this.body.style.maxHeight = Math.max(this._editor.getLayoutInfo().height / 4, 250) + 'px'; - this.body.style.maxWidth = Math.max(this._editor.getLayoutInfo().width * 0.66, 500) + 'px'; - this.body.tabIndex = 0; - this.body.appendChild(fragment); + this._body.classList.add('standalone-colorpicker-body'); + this._body.style.maxHeight = Math.max(this._editor.getLayoutInfo().height / 4, 250) + 'px'; + this._body.style.maxWidth = Math.max(this._editor.getLayoutInfo().width * 0.66, 500) + 'px'; + this._body.tabIndex = 0; + this._body.appendChild(fragment); colorPickerWidget.layout(); const colorPickerBody = colorPickerWidget.body; From 3165d7d7e9d96dc193e7d39175c7e392e460f620 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 21 Aug 2023 12:23:25 +0200 Subject: [PATCH 047/221] voice - adopt `AbortSignal` --- .../node/voiceRecognitionService.ts | 17 +++++++++++++++-- .../actions/chatVoiceInputActions.ts | 3 ++- .../workbenchVoiceRecognitionService.ts | 2 -- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/vs/platform/voiceRecognition/node/voiceRecognitionService.ts b/src/vs/platform/voiceRecognition/node/voiceRecognitionService.ts index 71c72a1c814..d2279001d75 100644 --- a/src/vs/platform/voiceRecognition/node/voiceRecognitionService.ts +++ b/src/vs/platform/voiceRecognition/node/voiceRecognitionService.ts @@ -45,7 +45,19 @@ export class VoiceRecognitionService implements IVoiceRecognitionService { const now = Date.now(); - const voiceModule: { transcribe: (audioBuffer: { channelCount: 1; samplingRate: 16000; bitDepth: 16; channelData: Float32Array }, options: { language: string | 'auto'; suppressNonSpeechTokens: boolean }) => Promise } = require.__$__nodeRequire(modulePath); + const voiceModule: { + transcribe: ( + audioBuffer: { channelCount: 1; samplingRate: 16000; bitDepth: 16; channelData: Float32Array }, + options: { + language: string | 'auto'; + suppressNonSpeechTokens: boolean; + signal: AbortSignal; + } + ) => Promise; + } = require.__$__nodeRequire(modulePath); + + const abortController = new AbortController(); + cancellation.onCancellationRequested(() => abortController.abort()); const text = await voiceModule.transcribe({ samplingRate: 16000, @@ -54,7 +66,8 @@ export class VoiceRecognitionService implements IVoiceRecognitionService { channelData }, { language: 'en', - suppressNonSpeechTokens: true + suppressNonSpeechTokens: true, + signal: abortController.signal }); this.logService.info(`[voice] transcribe(${channelData.length}): End (text: "${text}", took: ${Date.now() - now}ms)`); diff --git a/src/vs/workbench/contrib/chat/electron-sandbox/actions/chatVoiceInputActions.ts b/src/vs/workbench/contrib/chat/electron-sandbox/actions/chatVoiceInputActions.ts index 48e4c3b3f7d..2cfbcf9d255 100644 --- a/src/vs/workbench/contrib/chat/electron-sandbox/actions/chatVoiceInputActions.ts +++ b/src/vs/workbench/contrib/chat/electron-sandbox/actions/chatVoiceInputActions.ts @@ -6,6 +6,7 @@ import { CancellationTokenSource } from 'vs/base/common/cancellation'; import { Codicon } from 'vs/base/common/codicons'; import { DisposableStore, toDisposable } from 'vs/base/common/lifecycle'; +import { equalsIgnoreCase } from 'vs/base/common/strings'; import { ServicesAccessor } from 'vs/editor/browser/editorExtensions'; import { localize } from 'vs/nls'; import { Action2, MenuId, registerAction2 } from 'vs/platform/actions/common/actions'; @@ -72,7 +73,7 @@ class ChatVoiceInputSession { this.currentChatVoiceInputSession.add(onDidTranscribe(text => { if (text) { - if (lastText === text) { + if (lastText && equalsIgnoreCase(text, lastText)) { lastTextEqualCount++; if (lastTextEqualCount >= 2) { diff --git a/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts b/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts index cc159e4f06b..397877ca471 100644 --- a/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts +++ b/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts @@ -61,8 +61,6 @@ class VoiceTranscriptionWorkletNode extends AudioWorkletNode { } } -// TODO@voice -// - pass cancellation down into the node module via AbortSignal export class WorkbenchVoiceRecognitionService implements IWorkbenchVoiceRecognitionService { declare readonly _serviceBrand: undefined; From c3a4fbbe8f0c285eb1bb1a3c737b7b368a41e333 Mon Sep 17 00:00:00 2001 From: Ulugbek Abdullaev Date: Mon, 21 Aug 2023 13:00:50 +0200 Subject: [PATCH 048/221] add `vscode.executeMappedEditsProvider` command & use it to have integration tests for mapped-edits service --- build/lib/i18n.resources.json | 4 + .../singlefolder-tests/mappedEdits.test.ts | 102 ++++++++++++++++++ .../vscode-api-tests/testWorkspace/myFile.ts | 3 + .../api/browser/mainThreadMappedEdits.ts | 2 +- .../api/common/extHostApiCommands.ts | 21 +++- .../workbench/api/common/extHostCommands.ts | 10 ++ .../api/common/extHostTypeConverters.ts | 25 +++++ .../common/mappedEdits.contribution.ts | 49 +++++++++ .../mappedEdits/common/mappedEdits.ts | 8 +- src/vs/workbench/workbench.common.main.ts | 3 + 10 files changed, 221 insertions(+), 6 deletions(-) create mode 100644 extensions/vscode-api-tests/src/singlefolder-tests/mappedEdits.test.ts create mode 100644 extensions/vscode-api-tests/testWorkspace/myFile.ts create mode 100644 src/vs/workbench/contrib/mappedEdits/common/mappedEdits.contribution.ts diff --git a/build/lib/i18n.resources.json b/build/lib/i18n.resources.json index f83225cc974..f7f31337124 100644 --- a/build/lib/i18n.resources.json +++ b/build/lib/i18n.resources.json @@ -58,6 +58,10 @@ "name": "vs/workbench/contrib/commands", "project": "vscode-workbench" }, + { + "name": "vs/workbench/contrib/mappedEdits", + "project": "vscode-workbench" + }, { "name": "vs/workbench/contrib/comments", "project": "vscode-workbench" diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/mappedEdits.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/mappedEdits.test.ts new file mode 100644 index 00000000000..f4fc349f115 --- /dev/null +++ b/extensions/vscode-api-tests/src/singlefolder-tests/mappedEdits.test.ts @@ -0,0 +1,102 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as path from 'path'; +import * as vscode from 'vscode'; +import * as assert from 'assert'; + +suite('mapped edits provider', () => { + + test('mapped edits does not provide edits for unregistered langs', async function () { + + const uri = vscode.Uri.file(path.join(vscode.workspace.rootPath || '', './myFile.ts')); + + const tsDocFilter = [{ language: 'json' }]; + + const r1 = vscode.chat.registerMappedEditsProvider(tsDocFilter, { + provideMappedEdits: (_doc: vscode.TextDocument, codeBlocks: string[], context: vscode.MappedEditsContext, _token: vscode.CancellationToken) => { + + assert(context.selections.length === 1); + assert(context.related.length === 1); + assert('uri' in context.related[0] && 'range' in context.related[0]); + + const edit = new vscode.WorkspaceEdit(); + const text = codeBlocks.join('\n//----\n'); + edit.replace(uri, context.selections[0], text); + return edit; + } + }); + await vscode.workspace.openTextDocument(uri); + const result = await vscode.commands.executeCommand>( + 'vscode.executeMappedEditsProvider', + uri, + [ + '// hello', + `function foo() {\n\treturn 1;\n}`, + ], + { + selections: [new vscode.Selection(0, 0, 1, 0)], + related: [ + { + uri, + range: new vscode.Range(new vscode.Position(0, 0), new vscode.Position(1, 0)) + } + ] + } + ); + r1.dispose(); + + assert(result === null, 'returned null'); + }); + + test('mapped edits provides a single edit replacing the selection', async function () { + + const uri = vscode.Uri.file(path.join(vscode.workspace.rootPath || '', './myFile.ts')); + + const tsDocFilter = [{ language: 'typescript' }]; + + const r1 = vscode.chat.registerMappedEditsProvider(tsDocFilter, { + provideMappedEdits: (_doc: vscode.TextDocument, codeBlocks: string[], context: vscode.MappedEditsContext, _token: vscode.CancellationToken) => { + + assert(context.selections.length === 1); + assert(context.related.length === 1); + assert('uri' in context.related[0] && 'range' in context.related[0]); + + const edit = new vscode.WorkspaceEdit(); + const text = codeBlocks.join('\n//----\n'); + edit.replace(uri, context.selections[0], text); + return edit; + } + }); + + await vscode.workspace.openTextDocument(uri); + const result = await vscode.commands.executeCommand>( + 'vscode.executeMappedEditsProvider', + uri, + [ + '// hello', + `function foo() {\n\treturn 1;\n}`, + ], + { + selections: [new vscode.Selection(0, 0, 1, 0)], + related: [ + { + uri, + range: new vscode.Range(new vscode.Position(0, 0), new vscode.Position(1, 0)) + } + ] + } + ); + r1.dispose(); + + assert(result, 'non null response'); + const edits = result.get(uri); + assert(edits.length === 1); + assert(edits[0].range.start.line === 0); + assert(edits[0].range.start.character === 0); + assert(edits[0].range.end.line === 1); + assert(edits[0].range.end.character === 0); + }); +}); diff --git a/extensions/vscode-api-tests/testWorkspace/myFile.ts b/extensions/vscode-api-tests/testWorkspace/myFile.ts new file mode 100644 index 00000000000..2a2a4927869 --- /dev/null +++ b/extensions/vscode-api-tests/testWorkspace/myFile.ts @@ -0,0 +1,3 @@ +// 1 +// 2 +// 3 diff --git a/src/vs/workbench/api/browser/mainThreadMappedEdits.ts b/src/vs/workbench/api/browser/mainThreadMappedEdits.ts index a2a34f4155d..a268da7bbe1 100644 --- a/src/vs/workbench/api/browser/mainThreadMappedEdits.ts +++ b/src/vs/workbench/api/browser/mainThreadMappedEdits.ts @@ -6,7 +6,7 @@ import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity'; import { reviveWorkspaceEditDto } from 'vs/workbench/api/browser/mainThreadBulkEdits'; -import { ExtHostContext, ExtHostMappedEditsShape, IDocumentFilterDto, IMappedEditsContextDto, MainContext, MainThreadMappedEditsShape } from 'vs/workbench/api/common/extHost.protocol'; +import { ExtHostContext, ExtHostMappedEditsShape, IDocumentFilterDto, MainContext, MainThreadMappedEditsShape } from 'vs/workbench/api/common/extHost.protocol'; import { IMappedEditsProvider, IMappedEditsService } from 'vs/workbench/services/mappedEdits/common/mappedEdits'; import { IExtHostContext, extHostNamedCustomer } from 'vs/workbench/services/extensions/common/extHostCustomers'; diff --git a/src/vs/workbench/api/common/extHostApiCommands.ts b/src/vs/workbench/api/common/extHostApiCommands.ts index 68db008d1b1..fdb8ffa2cd6 100644 --- a/src/vs/workbench/api/common/extHostApiCommands.ts +++ b/src/vs/workbench/api/common/extHostApiCommands.ts @@ -464,7 +464,26 @@ const newCommands: ApiCommand[] = [ new ApiCommandArgument('value', 'The context key value', () => true, v => v), ], ApiCommandResult.Void - ) + ), + // --- mapped edits + new ApiCommand( + 'vscode.executeMappedEditsProvider', '_executeMappedEditsProvider', 'Execute Mapped Edits Provider', + [ + ApiCommandArgument.Uri, + ApiCommandArgument.StringArray, + new ApiCommandArgument( + 'MappedEditsContext', + 'Mapped Edits Context', + (v: unknown) => typeConverters.MappedEditsContext.is(v), + (v: vscode.MappedEditsContext) => typeConverters.MappedEditsContext.from(v) + ) + ], + new ApiCommandResult( + 'A promise that resolves to a workspace edit or null', + (value) => { + return typeConverters.WorkspaceEdit.to(value); + }) + ), ]; //#endregion diff --git a/src/vs/workbench/api/common/extHostCommands.ts b/src/vs/workbench/api/common/extHostCommands.ts index e8fc48765c7..fd3ba6c52b9 100644 --- a/src/vs/workbench/api/common/extHostCommands.ts +++ b/src/vs/workbench/api/common/extHostCommands.ts @@ -444,6 +444,16 @@ export class ApiCommandArgument { static readonly Selection = new ApiCommandArgument('selection', 'A selection in a text document', v => extHostTypes.Selection.isSelection(v), extHostTypeConverter.Selection.from); static readonly Number = new ApiCommandArgument('number', '', v => typeof v === 'number', v => v); static readonly String = new ApiCommandArgument('string', '', v => typeof v === 'string', v => v); + static readonly StringArray = ApiCommandArgument.Arr(ApiCommandArgument.String); + + static Arr(element: ApiCommandArgument) { + return new ApiCommandArgument( + `${element.name}_array`, + `Array of ${element.name}, ${element.description}`, + (v: unknown) => Array.isArray(v) && v.every(e => element.validate(e)), + (v: T[]) => v.map(e => element.convert(e)) + ); + } static readonly CallHierarchyItem = new ApiCommandArgument('item', 'A call hierarchy item', v => v instanceof extHostTypes.CallHierarchyItem, extHostTypeConverter.CallHierarchyItem.from); static readonly TypeHierarchyItem = new ApiCommandArgument('item', 'A type hierarchy item', v => v instanceof extHostTypes.TypeHierarchyItem, extHostTypeConverter.TypeHierarchyItem.from); diff --git a/src/vs/workbench/api/common/extHostTypeConverters.ts b/src/vs/workbench/api/common/extHostTypeConverters.ts index d0e1bc99d4a..0f7efee2be4 100644 --- a/src/vs/workbench/api/common/extHostTypeConverters.ts +++ b/src/vs/workbench/api/common/extHostTypeConverters.ts @@ -32,6 +32,7 @@ import { IMarkerData, IRelatedInformation, MarkerSeverity, MarkerTag } from 'vs/ import { ProgressLocation as MainProgressLocation } from 'vs/platform/progress/common/progress'; import * as extHostProtocol from 'vs/workbench/api/common/extHost.protocol'; import { getPrivateApiFor } from 'vs/workbench/api/common/extHostTestingPrivateApi'; +import type * as mappedEdits from 'vs/workbench/services/mappedEdits/common/mappedEdits'; import { DEFAULT_EDITOR_ASSOCIATION, SaveReason } from 'vs/workbench/common/editor'; import { IViewBadge } from 'vs/workbench/common/views'; import { IChatFollowup, IChatReplyFollowup, IChatResponseCommandFollowup } from 'vs/workbench/contrib/chat/common/chatService'; @@ -1563,6 +1564,30 @@ export namespace LanguageSelector { } } +export namespace MappedEditsContext { + + export function is(v: unknown): v is vscode.MappedEditsContext { + return (!!v && + typeof v === 'object' && + 'selections' in v && + Array.isArray(v.selections) && + v.selections.every(s => s instanceof types.Selection) && + 'related' in v && + Array.isArray(v.related) && + v.related.every(e => e && typeof e === 'object' && URI.isUri(e.uri) && e.range instanceof types.Range)); + } + + export function from(context: vscode.MappedEditsContext): mappedEdits.MappedEditsContext { + return { + selections: context.selections.map(s => Selection.from(s)), + related: context.related.map(r => ({ + uri: URI.from(r.uri), + range: Range.from(r.range) + })) + }; + } +} + export namespace NotebookRange { export function from(range: vscode.NotebookRange): ICellRange { diff --git a/src/vs/workbench/contrib/mappedEdits/common/mappedEdits.contribution.ts b/src/vs/workbench/contrib/mappedEdits/common/mappedEdits.contribution.ts new file mode 100644 index 00000000000..469d369d14a --- /dev/null +++ b/src/vs/workbench/contrib/mappedEdits/common/mappedEdits.contribution.ts @@ -0,0 +1,49 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { CancellationTokenSource } from 'vs/base/common/cancellation'; +import { URI } from 'vs/base/common/uri'; +import { ITextModelService } from 'vs/editor/common/services/resolverService'; +import * as nls from 'vs/nls'; +import { Action2, registerAction2 } from 'vs/platform/actions/common/actions'; +import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; +import { IMappedEditsService, MappedEditsContext } from 'vs/workbench/services/mappedEdits/common/mappedEdits'; + +class ExecuteMappedEditsProvider extends Action2 { + + static readonly ID = '_executeMappedEditsProvider'; + + constructor() { + super({ + id: ExecuteMappedEditsProvider.ID, + title: { value: nls.localize('executeMappedEditsProvider', "Execute Mapped Edits Provider"), original: '' }, + f1: false, + description: { + description: nls.localize('executeMappedEditsProvider.description', "Executes Mapped Edits Provider and returns the corresponding WorkspaceEdit or null if no edits are provided."), + args: [ + // FIXME@ulugbekna + ] + } + }); + } + + async run(accessor: ServicesAccessor, documentUri: URI, codeBlocks: string[], context: MappedEditsContext) { + + const mappedEditsService = accessor.get(IMappedEditsService); + const modelService = accessor.get(ITextModelService); + + const document = await modelService.createModelReference(documentUri); + + const cancellationTokenSource = new CancellationTokenSource(); + + const res = await mappedEditsService.provideMappedEdits(document.object.textEditorModel, codeBlocks, context, cancellationTokenSource.token); + + document.dispose(); + + return res; + } +} + +registerAction2(ExecuteMappedEditsProvider); diff --git a/src/vs/workbench/services/mappedEdits/common/mappedEdits.ts b/src/vs/workbench/services/mappedEdits/common/mappedEdits.ts index 8e58c5c1031..9a60304881c 100644 --- a/src/vs/workbench/services/mappedEdits/common/mappedEdits.ts +++ b/src/vs/workbench/services/mappedEdits/common/mappedEdits.ts @@ -10,16 +10,16 @@ import { LanguageSelector } from 'vs/editor/common/languageSelector'; import { IDisposable } from 'vs/base/common/lifecycle'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { WorkspaceEdit } from 'vs/editor/common/languages'; -import { Selection } from 'vs/editor/common/core/selection'; -import { Range } from 'vs/editor/common/core/range'; +import { ISelection } from 'vs/editor/common/core/selection'; +import { IRange } from 'vs/editor/common/core/range'; export interface RelatedContextItem { readonly uri: URI; - readonly range: Range; + readonly range: IRange; } export interface MappedEditsContext { - selections: Selection[]; + selections: ISelection[]; /** * If there's no context, the array should be empty. It's also empty until we figure out how to compute this or retrieve from an extension (eg, copilot chat) diff --git a/src/vs/workbench/workbench.common.main.ts b/src/vs/workbench/workbench.common.main.ts index 81170dfd99e..d30cd73ec49 100644 --- a/src/vs/workbench/workbench.common.main.ts +++ b/src/vs/workbench/workbench.common.main.ts @@ -227,6 +227,9 @@ import 'vs/workbench/contrib/markers/browser/markers.contribution'; // Merge Editor import 'vs/workbench/contrib/mergeEditor/browser/mergeEditor.contribution'; +// Mapped Edits +import 'vs/workbench/contrib/mappedEdits/common/mappedEdits.contribution'; + // Commands import 'vs/workbench/contrib/commands/common/commands.contribution'; From b289e3e7e0072ab6eec16c46e377df94e8e8c31e Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 21 Aug 2023 14:52:12 +0200 Subject: [PATCH 049/221] voice - add a command for quick voice chat --- src/vs/workbench/contrib/chat/browser/chat.ts | 1 + .../contrib/chat/browser/chatQuick.ts | 14 +++++-- .../actions/chatVoiceInputActions.ts | 40 +++++++++++++++++-- 3 files changed, 48 insertions(+), 7 deletions(-) diff --git a/src/vs/workbench/contrib/chat/browser/chat.ts b/src/vs/workbench/contrib/chat/browser/chat.ts index 6d164721797..303e525c6b1 100644 --- a/src/vs/workbench/contrib/chat/browser/chat.ts +++ b/src/vs/workbench/contrib/chat/browser/chat.ts @@ -38,6 +38,7 @@ export interface IQuickChatService { enabled: boolean; toggle(providerId?: string, query?: string): void; focus(): void; + open(): void; close(): void; openInChatView(): void; } diff --git a/src/vs/workbench/contrib/chat/browser/chatQuick.ts b/src/vs/workbench/contrib/chat/browser/chatQuick.ts index e43c684102d..3729e4fffb7 100644 --- a/src/vs/workbench/contrib/chat/browser/chatQuick.ts +++ b/src/vs/workbench/contrib/chat/browser/chatQuick.ts @@ -20,8 +20,8 @@ import { IChatService } from 'vs/workbench/contrib/chat/common/chatService'; export class QuickChatService implements IQuickChatService { readonly _serviceBrand: undefined; - _input: IQuickWidget | undefined; - _currentChat: QuickChat | undefined; + private _input: IQuickWidget | undefined; + private _currentChat: QuickChat | undefined; constructor( @IQuickInputService private readonly quickInputService: IQuickInputService, @@ -34,7 +34,7 @@ export class QuickChatService implements IQuickChatService { } get focused(): boolean { - const widget = this._input?.widget as HTMLElement; + const widget = this._input?.widget as HTMLElement | undefined; if (!widget) { return false; } @@ -45,7 +45,13 @@ export class QuickChatService implements IQuickChatService { // If the input is already shown, hide it. This provides a toggle behavior of the quick pick if (this.focused) { this.close(); - return; + } else { + this.open(providerId, query); + } + } + open(providerId?: string, query?: string | undefined): void { + if (this.focused) { + return this.focus(); } // Check if any providers are available. If not, show nothing diff --git a/src/vs/workbench/contrib/chat/electron-sandbox/actions/chatVoiceInputActions.ts b/src/vs/workbench/contrib/chat/electron-sandbox/actions/chatVoiceInputActions.ts index 2cfbcf9d255..ea6cec92cc8 100644 --- a/src/vs/workbench/contrib/chat/electron-sandbox/actions/chatVoiceInputActions.ts +++ b/src/vs/workbench/contrib/chat/electron-sandbox/actions/chatVoiceInputActions.ts @@ -13,7 +13,8 @@ import { Action2, MenuId, registerAction2 } from 'vs/platform/actions/common/act import { IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { spinningLoading } from 'vs/platform/theme/common/iconRegistry'; -import { IChatWidget } from 'vs/workbench/contrib/chat/browser/chat'; +import { CHAT_CATEGORY } from 'vs/workbench/contrib/chat/browser/actions/chatActions'; +import { IChatWidget, IChatWidgetService, IQuickChatService } from 'vs/workbench/contrib/chat/browser/chat'; import { IWorkbenchVoiceRecognitionService } from 'vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService'; const CONTEXT_CHAT_VOICE_INPUT_GETTING_READY = new RawContextKey('chatVoiceInputGettingReady', false, { type: 'boolean', description: localize('chatVoiceInputGettingReady', "True when there is voice input for chat getting ready.") }); @@ -116,6 +117,7 @@ class StartChatVoiceInputAction extends Action2 { value: localize('interactive.voiceInput.label', "Start Voice Input"), original: 'Start Voice Input' }, + category: CHAT_CATEGORY, icon: Codicon.record, precondition: CONTEXT_CHAT_VOICE_INPUT_GETTING_READY.negate(), menu: { @@ -127,7 +129,7 @@ class StartChatVoiceInputAction extends Action2 { }); } - run(accessor: ServicesAccessor, ...args: any[]) { + run(accessor: ServicesAccessor, ...args: any[]): void { const context = args[0]; if (!isVoiceInputActionContext(context)) { return; @@ -147,6 +149,9 @@ class StopChatVoiceInputAction extends Action2 { value: localize('interactive.stopVoiceInput.label', "Stop Voice Input"), original: 'Stop Voice Input' }, + category: CHAT_CATEGORY, + f1: true, + precondition: CONTEXT_CHAT_VOICE_INPUT_IN_PROGRESS, icon: spinningLoading, menu: { id: MenuId.ChatExecute, @@ -157,12 +162,41 @@ class StopChatVoiceInputAction extends Action2 { }); } - run(accessor: ServicesAccessor) { + run(accessor: ServicesAccessor): void { ChatVoiceInputSession.getInstance(accessor.get(IInstantiationService)).stop(); } } +class StartVoiceQuickChatAction extends Action2 { + static readonly ID = 'workbench.action.chat.startVoiceQuickChat'; + + constructor() { + super({ + id: StartVoiceQuickChatAction.ID, + title: { + value: localize('interactive.startVoiceChat.label', "Start Voice Quick Chat"), + original: 'Start Voice Quick Chat' + }, + category: CHAT_CATEGORY, + f1: true + }); + } + + run(accessor: ServicesAccessor): void { + const quickChatService = accessor.get(IQuickChatService); + const chatWidgetService = accessor.get(IChatWidgetService); + + quickChatService.open(); + + const widget = chatWidgetService.lastFocusedWidget; + if (widget) { + ChatVoiceInputSession.getInstance(accessor.get(IInstantiationService)).start({ widget }); + } + } +} + export function registerChatVoiceInputActions() { registerAction2(StartChatVoiceInputAction); registerAction2(StopChatVoiceInputAction); + registerAction2(StartVoiceQuickChatAction); } From 165782617525c6da5c67033245e15770937a23d4 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 21 Aug 2023 15:03:20 +0200 Subject: [PATCH 050/221] voice - allow to start voice input to focussed chat widget via command --- src/vs/workbench/contrib/chat/browser/chat.ts | 1 + src/vs/workbench/contrib/chat/browser/chatInputPart.ts | 4 ++++ src/vs/workbench/contrib/chat/browser/chatWidget.ts | 4 ++++ .../electron-sandbox/actions/chatVoiceInputActions.ts | 10 ++++++++-- 4 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/chat/browser/chat.ts b/src/vs/workbench/contrib/chat/browser/chat.ts index 303e525c6b1..7450fb52efa 100644 --- a/src/vs/workbench/contrib/chat/browser/chat.ts +++ b/src/vs/workbench/contrib/chat/browser/chat.ts @@ -94,6 +94,7 @@ export interface IChatWidget { acceptInput(query?: string): void; focusLastMessage(): void; focusInput(): void; + hasInputFocus(): boolean; getSlashCommands(): Promise; getCodeBlockInfoForEditor(uri: URI): IChatCodeBlockInfo | undefined; getCodeBlockInfosForResponse(response: IChatResponseViewModel): IChatCodeBlockInfo[]; diff --git a/src/vs/workbench/contrib/chat/browser/chatInputPart.ts b/src/vs/workbench/contrib/chat/browser/chatInputPart.ts index d0982610acd..df657d54439 100644 --- a/src/vs/workbench/contrib/chat/browser/chatInputPart.ts +++ b/src/vs/workbench/contrib/chat/browser/chatInputPart.ts @@ -150,6 +150,10 @@ export class ChatInputPart extends Disposable implements IHistoryNavigationWidge this._inputEditor.focus(); } + hasFocus(): boolean { + return this._inputEditor.hasWidgetFocus(); + } + async acceptInput(query?: string | IChatReplyFollowup): Promise { const editorValue = this._inputEditor.getValue(); if (!query && editorValue) { diff --git a/src/vs/workbench/contrib/chat/browser/chatWidget.ts b/src/vs/workbench/contrib/chat/browser/chatWidget.ts index aca5a1d961f..053278d5af6 100644 --- a/src/vs/workbench/contrib/chat/browser/chatWidget.ts +++ b/src/vs/workbench/contrib/chat/browser/chatWidget.ts @@ -182,6 +182,10 @@ export class ChatWidget extends Disposable implements IChatWidget { this.inputPart.focus(); } + hasInputFocus(): boolean { + return this.inputPart.hasFocus(); + } + moveFocus(item: ChatTreeItem, type: 'next' | 'previous'): void { const items = this.viewModel?.getItems(); if (!items) { diff --git a/src/vs/workbench/contrib/chat/electron-sandbox/actions/chatVoiceInputActions.ts b/src/vs/workbench/contrib/chat/electron-sandbox/actions/chatVoiceInputActions.ts index ea6cec92cc8..9e3058c7405 100644 --- a/src/vs/workbench/contrib/chat/electron-sandbox/actions/chatVoiceInputActions.ts +++ b/src/vs/workbench/contrib/chat/electron-sandbox/actions/chatVoiceInputActions.ts @@ -130,9 +130,15 @@ class StartChatVoiceInputAction extends Action2 { } run(accessor: ServicesAccessor, ...args: any[]): void { - const context = args[0]; + const chatWidgetService = accessor.get(IChatWidgetService); + + let context = args[0]; if (!isVoiceInputActionContext(context)) { - return; + if (chatWidgetService.lastFocusedWidget?.hasInputFocus()) { + context = { widget: chatWidgetService.lastFocusedWidget }; + } else { + return; + } } ChatVoiceInputSession.getInstance(accessor.get(IInstantiationService)).start(context); From d2624165dfee5116eb08c3fc19c9432345ce9f40 Mon Sep 17 00:00:00 2001 From: Ulugbek Abdullaev Date: Mon, 21 Aug 2023 15:59:00 +0200 Subject: [PATCH 051/221] refactor: `_executeMappedEditsProvider` command doesn't need to be an action --- .../common/mappedEdits.contribution.ts | 42 +++++-------------- 1 file changed, 10 insertions(+), 32 deletions(-) diff --git a/src/vs/workbench/contrib/mappedEdits/common/mappedEdits.contribution.ts b/src/vs/workbench/contrib/mappedEdits/common/mappedEdits.contribution.ts index 469d369d14a..82171c7fbed 100644 --- a/src/vs/workbench/contrib/mappedEdits/common/mappedEdits.contribution.ts +++ b/src/vs/workbench/contrib/mappedEdits/common/mappedEdits.contribution.ts @@ -6,44 +6,22 @@ import { CancellationTokenSource } from 'vs/base/common/cancellation'; import { URI } from 'vs/base/common/uri'; import { ITextModelService } from 'vs/editor/common/services/resolverService'; -import * as nls from 'vs/nls'; -import { Action2, registerAction2 } from 'vs/platform/actions/common/actions'; +import { CommandsRegistry } from 'vs/platform/commands/common/commands'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { IMappedEditsService, MappedEditsContext } from 'vs/workbench/services/mappedEdits/common/mappedEdits'; -class ExecuteMappedEditsProvider extends Action2 { +CommandsRegistry.registerCommand('_executeMappedEditsProvider', async (accessor: ServicesAccessor, documentUri: URI, codeBlocks: string[], context: MappedEditsContext) => { - static readonly ID = '_executeMappedEditsProvider'; + const mappedEditsService = accessor.get(IMappedEditsService); + const modelService = accessor.get(ITextModelService); - constructor() { - super({ - id: ExecuteMappedEditsProvider.ID, - title: { value: nls.localize('executeMappedEditsProvider', "Execute Mapped Edits Provider"), original: '' }, - f1: false, - description: { - description: nls.localize('executeMappedEditsProvider.description', "Executes Mapped Edits Provider and returns the corresponding WorkspaceEdit or null if no edits are provided."), - args: [ - // FIXME@ulugbekna - ] - } - }); - } + const document = await modelService.createModelReference(documentUri); - async run(accessor: ServicesAccessor, documentUri: URI, codeBlocks: string[], context: MappedEditsContext) { + const cancellationTokenSource = new CancellationTokenSource(); - const mappedEditsService = accessor.get(IMappedEditsService); - const modelService = accessor.get(ITextModelService); + const result = await mappedEditsService.provideMappedEdits(document.object.textEditorModel, codeBlocks, context, cancellationTokenSource.token); - const document = await modelService.createModelReference(documentUri); + document.dispose(); - const cancellationTokenSource = new CancellationTokenSource(); - - const res = await mappedEditsService.provideMappedEdits(document.object.textEditorModel, codeBlocks, context, cancellationTokenSource.token); - - document.dispose(); - - return res; - } -} - -registerAction2(ExecuteMappedEditsProvider); + return result; +}); From 76cc0881d31d6d8869eb4677c1777741e0401535 Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Mon, 21 Aug 2023 16:24:57 +0200 Subject: [PATCH 052/221] using instead the uri string --- .../src/languageFeatures/diagnostics.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts b/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts index fb09cee0b04..b55ed3af3d8 100644 --- a/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts +++ b/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts @@ -153,7 +153,7 @@ class DiagnosticSettings { class DiagnosticsTelemetryManager extends Disposable { private readonly _diagnosticCodesMap = new Map(); - private readonly _diagnosticSnapshotsMap = new Map(); + private readonly _diagnosticSnapshotsMap = new Map(); private _timeout: NodeJS.Timeout | undefined; constructor( @@ -181,9 +181,10 @@ class DiagnosticsTelemetryManager extends Disposable { } private _updateDiagnosticCodes(uri: vscode.Uri) { - const previousDiagnostics = this._diagnosticSnapshotsMap.get(uri); + const uriString = uri.toString(); + const previousDiagnostics = this._diagnosticSnapshotsMap.get(uriString); const currentDiagnostics = this._getDiagnostics(uri); - this._diagnosticSnapshotsMap.set(uri, currentDiagnostics); + this._diagnosticSnapshotsMap.set(uriString, currentDiagnostics); const diagnosticsDiff = currentDiagnostics.filter((diagnostic) => !previousDiagnostics?.some((previousDiagnostic) => JSON.stringify(diagnostic) === JSON.stringify(previousDiagnostic))); diagnosticsDiff.forEach((diagnostic) => { const code = diagnostic.code; From cf21c24624a62158dfb538fb726a8da3531684b5 Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Mon, 21 Aug 2023 16:48:48 +0200 Subject: [PATCH 053/221] updating all the diagnostics after the timeout --- .../src/languageFeatures/diagnostics.ts | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts b/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts index b55ed3af3d8..f98c7998e3d 100644 --- a/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts +++ b/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts @@ -163,7 +163,7 @@ class DiagnosticsTelemetryManager extends Disposable { super(); this._register(vscode.workspace.onDidChangeTextDocument(e => { if (e.document.languageId === 'typescript') { - this._updateDiagnosticCodesAfterTimeoutForUri(e.document.uri); + this._updateAllDiagnosticCodesAfterTimeout(); } })); this._updateAllDiagnosticCodesAfterTimeout(); @@ -171,13 +171,9 @@ class DiagnosticsTelemetryManager extends Disposable { } private _updateAllDiagnosticCodesAfterTimeout() { - const uris = vscode.workspace.textDocuments.map(doc => doc.uri); - uris.forEach(uri => setTimeout(() => { this._updateDiagnosticCodes(uri); }, 10000)); - } - - private _updateDiagnosticCodesAfterTimeoutForUri(uri: vscode.Uri) { clearTimeout(this._timeout); - this._timeout = setTimeout(() => { this._updateDiagnosticCodes(uri); }, 10000); + const uris = vscode.workspace.textDocuments.map(doc => doc.uri); + this._timeout = setTimeout(() => { uris.forEach((uri) => this._updateDiagnosticCodes(uri)); }, 5000); } private _updateDiagnosticCodes(uri: vscode.Uri) { @@ -185,7 +181,9 @@ class DiagnosticsTelemetryManager extends Disposable { const previousDiagnostics = this._diagnosticSnapshotsMap.get(uriString); const currentDiagnostics = this._getDiagnostics(uri); this._diagnosticSnapshotsMap.set(uriString, currentDiagnostics); - const diagnosticsDiff = currentDiagnostics.filter((diagnostic) => !previousDiagnostics?.some((previousDiagnostic) => JSON.stringify(diagnostic) === JSON.stringify(previousDiagnostic))); + const diagnosticsDiff = currentDiagnostics.filter((diagnostic) => !previousDiagnostics?.some((previousDiagnostic) => { + return diagnostic === previousDiagnostic; + })); diagnosticsDiff.forEach((diagnostic) => { const code = diagnostic.code; if (typeof code === 'string' || typeof code === 'number') { From 8db8d30dfa91585b75632f1d32747bb542a993d6 Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Mon, 21 Aug 2023 16:56:13 +0200 Subject: [PATCH 054/221] using the utility method equals --- .../src/languageFeatures/diagnostics.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts b/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts index f98c7998e3d..57f1d257bb2 100644 --- a/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts +++ b/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts @@ -10,6 +10,7 @@ import { Disposable } from '../utils/dispose'; import { ResourceMap } from '../utils/resourceMap'; import { TelemetryReporter } from '../logging/telemetry'; import { TypeScriptServiceConfiguration } from '../configuration/configuration'; +import { equals } from '../utils/objects'; function diagnosticsEquals(a: vscode.Diagnostic, b: vscode.Diagnostic): boolean { if (a === b) { @@ -181,9 +182,7 @@ class DiagnosticsTelemetryManager extends Disposable { const previousDiagnostics = this._diagnosticSnapshotsMap.get(uriString); const currentDiagnostics = this._getDiagnostics(uri); this._diagnosticSnapshotsMap.set(uriString, currentDiagnostics); - const diagnosticsDiff = currentDiagnostics.filter((diagnostic) => !previousDiagnostics?.some((previousDiagnostic) => { - return diagnostic === previousDiagnostic; - })); + const diagnosticsDiff = currentDiagnostics.filter((diagnostic) => !previousDiagnostics?.some((previousDiagnostic) => equals(diagnostic, previousDiagnostic))); diagnosticsDiff.forEach((diagnostic) => { const code = diagnostic.code; if (typeof code === 'string' || typeof code === 'number') { From fb4b533d9352f32297ae77b5ba6d7485bbbf69aa Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Mon, 21 Aug 2023 17:01:53 +0200 Subject: [PATCH 055/221] extracting the method _increaseDiagnosticCodeCount to avoid duplication --- .../src/languageFeatures/diagnostics.ts | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts b/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts index 57f1d257bb2..0743d34f0e2 100644 --- a/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts +++ b/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts @@ -177,6 +177,13 @@ class DiagnosticsTelemetryManager extends Disposable { this._timeout = setTimeout(() => { uris.forEach((uri) => this._updateDiagnosticCodes(uri)); }, 5000); } + private _increaseDiagnosticCodeCount(code: string | number | undefined) { + if (code === undefined) { + return; + } + this._diagnosticCodesMap.set(Number(code), (this._diagnosticCodesMap.get(Number(code)) || 0) + 1); + } + private _updateDiagnosticCodes(uri: vscode.Uri) { const uriString = uri.toString(); const previousDiagnostics = this._diagnosticSnapshotsMap.get(uriString); @@ -185,11 +192,7 @@ class DiagnosticsTelemetryManager extends Disposable { const diagnosticsDiff = currentDiagnostics.filter((diagnostic) => !previousDiagnostics?.some((previousDiagnostic) => equals(diagnostic, previousDiagnostic))); diagnosticsDiff.forEach((diagnostic) => { const code = diagnostic.code; - if (typeof code === 'string' || typeof code === 'number') { - this._diagnosticCodesMap.set(Number(code), (this._diagnosticCodesMap.get(Number(code)) || 0) + 1); - } else if (code !== undefined) { - this._diagnosticCodesMap.set(Number(code.value), (this._diagnosticCodesMap.get(Number(code.value)) || 0) + 1); - } + this._increaseDiagnosticCodeCount(typeof code === 'string' || typeof code === 'number' ? code : code?.value); }); } From 3eaaba268f2b2e1caa03cdb668cf081e701f7788 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 21 Aug 2023 17:36:53 +0200 Subject: [PATCH 056/221] voice - show error notification on error --- .../workbenchVoiceRecognitionService.ts | 116 ++++++++++-------- 1 file changed, 63 insertions(+), 53 deletions(-) diff --git a/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts b/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts index 397877ca471..3a10c4afa7b 100644 --- a/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts +++ b/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts @@ -12,6 +12,7 @@ import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/ import { DeferredPromise } from 'vs/base/common/async'; import { FileAccess } from 'vs/base/common/network'; import { ISharedProcessService } from 'vs/platform/ipc/electron-sandbox/services'; +import { INotificationService } from 'vs/platform/notification/common/notification'; export const IWorkbenchVoiceRecognitionService = createDecorator('workbenchVoiceRecognitionService'); @@ -61,6 +62,8 @@ class VoiceTranscriptionWorkletNode extends AudioWorkletNode { } } +// TODO@voice +// - add native module test to ensure module loads export class WorkbenchVoiceRecognitionService implements IWorkbenchVoiceRecognitionService { declare readonly _serviceBrand: undefined; @@ -71,7 +74,8 @@ export class WorkbenchVoiceRecognitionService implements IWorkbenchVoiceRecognit constructor( @IProgressService private readonly progressService: IProgressService, - @ISharedProcessService private readonly sharedProcessService: ISharedProcessService + @ISharedProcessService private readonly sharedProcessService: ISharedProcessService, + @INotificationService private readonly notificationService: INotificationService ) { } async transcribe(cancellation: CancellationToken): Promise> { @@ -92,65 +96,71 @@ export class WorkbenchVoiceRecognitionService implements IWorkbenchVoiceRecognit title: localize('voiceTranscription', "Voice Transcription"), }, async progress => { const recordingDone = new DeferredPromise(); + try { + progress.report({ message: localize('voiceTranscriptionGettingReady', "Getting microphone ready...") }); - progress.report({ message: localize('voiceTranscriptionGettingReady', "Getting microphone ready...") }); - - const microphoneDevice = await navigator.mediaDevices.getUserMedia({ - audio: { - sampleRate: WorkbenchVoiceRecognitionService.AUDIO_SAMPLING_RATE, - sampleSize: WorkbenchVoiceRecognitionService.AUDIO_BIT_DEPTH, - channelCount: WorkbenchVoiceRecognitionService.AUDIO_CHANNELS, - autoGainControl: true, - noiseSuppression: true - } - }); - - if (token.isCancellationRequested) { - return; - } - - const audioContext = new AudioContext({ - sampleRate: WorkbenchVoiceRecognitionService.AUDIO_SAMPLING_RATE, - latencyHint: 'interactive' - }); - - const microphoneSource = audioContext.createMediaStreamSource(microphoneDevice); - - token.onCancellationRequested(() => { - try { - for (const track of microphoneDevice.getTracks()) { - track.stop(); + const microphoneDevice = await navigator.mediaDevices.getUserMedia({ + audio: { + sampleRate: WorkbenchVoiceRecognitionService.AUDIO_SAMPLING_RATE, + sampleSize: WorkbenchVoiceRecognitionService.AUDIO_BIT_DEPTH, + channelCount: WorkbenchVoiceRecognitionService.AUDIO_CHANNELS, + autoGainControl: true, + noiseSuppression: true } + }); - microphoneSource.disconnect(); - audioContext.close(); - } finally { - recordingDone.complete(); + if (token.isCancellationRequested) { + return; } - }); - await audioContext.audioWorklet.addModule(FileAccess.asBrowserUri('vs/workbench/services/voiceRecognition/electron-sandbox/voiceTranscriptionWorklet.js').toString(true)); + const audioContext = new AudioContext({ + sampleRate: WorkbenchVoiceRecognitionService.AUDIO_SAMPLING_RATE, + latencyHint: 'interactive' + }); - if (token.isCancellationRequested) { - return; + const microphoneSource = audioContext.createMediaStreamSource(microphoneDevice); + + token.onCancellationRequested(() => { + try { + for (const track of microphoneDevice.getTracks()) { + track.stop(); + } + + microphoneSource.disconnect(); + audioContext.close(); + } finally { + recordingDone.complete(); + } + }); + + await audioContext.audioWorklet.addModule(FileAccess.asBrowserUri('vs/workbench/services/voiceRecognition/electron-sandbox/voiceTranscriptionWorklet.js').toString(true)); + + if (token.isCancellationRequested) { + return; + } + + const voiceTranscriptionTarget = new VoiceTranscriptionWorkletNode(audioContext, { + channelCount: WorkbenchVoiceRecognitionService.AUDIO_CHANNELS, + channelCountMode: 'explicit' + }, onDidTranscribe, this.sharedProcessService); + await voiceTranscriptionTarget.start(token); + + if (token.isCancellationRequested) { + return; + } + + microphoneSource.connect(voiceTranscriptionTarget); + + progress.report({ message: localize('voiceTranscriptionRecording', "Recording from microphone...") }); + recordingReady.complete(); + + return recordingDone.p; + } catch (error) { + this.notificationService.error(localize('voiceTranscriptionError', "Voice transcription failed: {0}", error.message)); + + recordingReady.error(error); + recordingDone.error(error); } - - const voiceTranscriptionTarget = new VoiceTranscriptionWorkletNode(audioContext, { - channelCount: WorkbenchVoiceRecognitionService.AUDIO_CHANNELS, - channelCountMode: 'explicit' - }, onDidTranscribe, this.sharedProcessService); - await voiceTranscriptionTarget.start(token); - - if (token.isCancellationRequested) { - return; - } - - microphoneSource.connect(voiceTranscriptionTarget); - - progress.report({ message: localize('voiceTranscriptionRecording', "Recording from microphone...") }); - recordingReady.complete(); - - return recordingDone.p; }); return recordingReady.p; From 5fbf0d2ed173d2819a4c3653485e3f4f6945bd9b Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Mon, 21 Aug 2023 17:42:44 +0200 Subject: [PATCH 057/221] passing in instead the diagnostic collection --- .../src/languageFeatures/diagnostics.ts | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts b/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts index 0743d34f0e2..80093b4701c 100644 --- a/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts +++ b/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts @@ -159,7 +159,7 @@ class DiagnosticsTelemetryManager extends Disposable { constructor( private readonly _telemetryReporter: TelemetryReporter, - private readonly _getDiagnostics: (uri: vscode.Uri) => readonly vscode.Diagnostic[] + private readonly _diagnosticsCollection: vscode.DiagnosticCollection, ) { super(); this._register(vscode.workspace.onDidChangeTextDocument(e => { @@ -173,8 +173,7 @@ class DiagnosticsTelemetryManager extends Disposable { private _updateAllDiagnosticCodesAfterTimeout() { clearTimeout(this._timeout); - const uris = vscode.workspace.textDocuments.map(doc => doc.uri); - this._timeout = setTimeout(() => { uris.forEach((uri) => this._updateDiagnosticCodes(uri)); }, 5000); + this._timeout = setTimeout(() => this._updateDiagnosticCodes(), 5000); } private _increaseDiagnosticCodeCount(code: string | number | undefined) { @@ -184,15 +183,16 @@ class DiagnosticsTelemetryManager extends Disposable { this._diagnosticCodesMap.set(Number(code), (this._diagnosticCodesMap.get(Number(code)) || 0) + 1); } - private _updateDiagnosticCodes(uri: vscode.Uri) { - const uriString = uri.toString(); - const previousDiagnostics = this._diagnosticSnapshotsMap.get(uriString); - const currentDiagnostics = this._getDiagnostics(uri); - this._diagnosticSnapshotsMap.set(uriString, currentDiagnostics); - const diagnosticsDiff = currentDiagnostics.filter((diagnostic) => !previousDiagnostics?.some((previousDiagnostic) => equals(diagnostic, previousDiagnostic))); - diagnosticsDiff.forEach((diagnostic) => { - const code = diagnostic.code; - this._increaseDiagnosticCodeCount(typeof code === 'string' || typeof code === 'number' ? code : code?.value); + private _updateDiagnosticCodes() { + this._diagnosticsCollection.forEach((uri, diagnostics) => { + const uriString = uri.toString(); + const previousDiagnostics = this._diagnosticSnapshotsMap.get(uriString); + this._diagnosticSnapshotsMap.set(uriString, diagnostics); + const diagnosticsDiff = diagnostics.filter((diagnostic) => !previousDiagnostics?.some((previousDiagnostic) => equals(diagnostic, previousDiagnostic))); + diagnosticsDiff.forEach((diagnostic) => { + const code = diagnostic.code; + this._increaseDiagnosticCodeCount(typeof code === 'string' || typeof code === 'number' ? code : code?.value); + }); }); } @@ -242,7 +242,7 @@ export class DiagnosticsManager extends Disposable { this._currentDiagnostics = this._register(vscode.languages.createDiagnosticCollection(owner)); // Here we are selecting only 1 user out of 1000 to send telemetry diagnostics if (Math.random() * 1000 <= 1 || configuration.enableDiagnosticsTelemetry) { - this._register(new DiagnosticsTelemetryManager(telemetryReporter, this.getDiagnostics.bind(this))); + this._register(new DiagnosticsTelemetryManager(telemetryReporter, this._currentDiagnostics)); } } From 458dc45528b15b56915e49e390dceee81f14b054 Mon Sep 17 00:00:00 2001 From: Jean Pierre Date: Mon, 21 Aug 2023 11:42:51 -0500 Subject: [PATCH 058/221] Fix #190499 --- src/vs/platform/terminal/node/ptyService.ts | 4 ++-- .../quickFix/browser/terminal.quickFix.contribution.ts | 2 +- .../quickFix/browser/terminalQuickFixBuiltinActions.ts | 7 ++----- .../quickFix/test/browser/quickFixAddon.test.ts | 7 +------ 4 files changed, 6 insertions(+), 14 deletions(-) diff --git a/src/vs/platform/terminal/node/ptyService.ts b/src/vs/platform/terminal/node/ptyService.ts index 7e017ab5ccd..31977e91c8c 100644 --- a/src/vs/platform/terminal/node/ptyService.ts +++ b/src/vs/platform/terminal/node/ptyService.ts @@ -161,9 +161,9 @@ export class PtyService extends Disposable implements IPtyService { resolve(stdout); }); }); - const processesForPort = stdout.split('\n'); + const processesForPort = stdout.split(/\r?\n/).filter(s => !!s.trim()); if (processesForPort.length >= 1) { - const capturePid = /\s+(\d+)\s+/; + const capturePid = /\s+(\d+)(?:\s+|$)/; const processId = processesForPort[0].match(capturePid)?.[1]; if (processId) { try { diff --git a/src/vs/workbench/contrib/terminalContrib/quickFix/browser/terminal.quickFix.contribution.ts b/src/vs/workbench/contrib/terminalContrib/quickFix/browser/terminal.quickFix.contribution.ts index f910bb1b7c3..96f2fccd74f 100644 --- a/src/vs/workbench/contrib/terminalContrib/quickFix/browser/terminal.quickFix.contribution.ts +++ b/src/vs/workbench/contrib/terminalContrib/quickFix/browser/terminal.quickFix.contribution.ts @@ -55,7 +55,7 @@ class TerminalQuickFixContribution extends DisposableStore implements ITerminalC // Register quick fixes for (const actionOption of [ gitTwoDashes(), - freePort(this), + freePort((port: string, command: string) => this._instance.freePortKillProcess(port, command)), gitSimilar(), gitPushSetUpstream(), gitCreatePr(), diff --git a/src/vs/workbench/contrib/terminalContrib/quickFix/browser/terminalQuickFixBuiltinActions.ts b/src/vs/workbench/contrib/terminalContrib/quickFix/browser/terminalQuickFixBuiltinActions.ts index 386eb5153fb..89284446f73 100644 --- a/src/vs/workbench/contrib/terminalContrib/quickFix/browser/terminalQuickFixBuiltinActions.ts +++ b/src/vs/workbench/contrib/terminalContrib/quickFix/browser/terminalQuickFixBuiltinActions.ts @@ -5,7 +5,6 @@ import { URI } from 'vs/base/common/uri'; import { localize } from 'vs/nls'; -import { ITerminalInstance } from 'vs/workbench/contrib/terminal/browser/terminal'; import { ITerminalQuickFixInternalOptions, ITerminalCommandMatchResult, ITerminalQuickFixExecuteTerminalCommandAction, TerminalQuickFixActionInternal, TerminalQuickFixType } from 'vs/workbench/contrib/terminalContrib/quickFix/browser/quickFix'; export const GitCommandLineRegex = /git/; @@ -88,7 +87,7 @@ export function gitTwoDashes(): ITerminalQuickFixInternalOptions { } }; } -export function freePort(terminalInstance?: Partial): ITerminalQuickFixInternalOptions { +export function freePort(runCallback: (port: string, commandLine: string) => Promise): ITerminalQuickFixInternalOptions { return { id: 'Free Port', type: 'internal', @@ -114,9 +113,7 @@ export function freePort(terminalInstance?: Partial): ITermin label, enabled: true, source: QuickFixSource.Builtin, - run: async () => { - await terminalInstance?.freePortKillProcess?.(port, matchResult.commandLine); - } + run: () => runCallback(port, matchResult.commandLine) }; } }; diff --git a/src/vs/workbench/contrib/terminalContrib/quickFix/test/browser/quickFixAddon.test.ts b/src/vs/workbench/contrib/terminalContrib/quickFix/test/browser/quickFixAddon.test.ts index 5d5a0a16a07..74d2ae5cd88 100644 --- a/src/vs/workbench/contrib/terminalContrib/quickFix/test/browser/quickFixAddon.test.ts +++ b/src/vs/workbench/contrib/terminalContrib/quickFix/test/browser/quickFixAddon.test.ts @@ -15,7 +15,6 @@ import { ILogService, NullLogService } from 'vs/platform/log/common/log'; import { ITerminalCommand, TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities'; import { CommandDetectionCapability } from 'vs/platform/terminal/common/capabilities/commandDetectionCapability'; import { TerminalCapabilityStore } from 'vs/platform/terminal/common/capabilities/terminalCapabilityStore'; -import { ITerminalInstance } from 'vs/workbench/contrib/terminal/browser/terminal'; import { gitSimilar, freePort, FreePortOutputRegex, gitCreatePr, GitCreatePrOutputRegex, GitPushOutputRegex, gitPushSetUpstream, GitSimilarOutputRegex, gitTwoDashes, GitTwoDashesRegex, pwshUnixCommandNotFoundError, PwshUnixCommandNotFoundErrorOutputRegex, pwshGeneralError, PwshGeneralErrorOutputRegex } from 'vs/workbench/contrib/terminalContrib/quickFix/browser/terminalQuickFixBuiltinActions'; import { TerminalQuickFixAddon, getQuickFixesForCommand } from 'vs/workbench/contrib/terminalContrib/quickFix/browser/quickFixAddon'; import { URI } from 'vs/base/common/uri'; @@ -34,7 +33,6 @@ import { TestCommandService } from 'vs/editor/test/browser/editorTestServices'; suite('QuickFixAddon', () => { let quickFixAddon: TerminalQuickFixAddon; - let terminalInstance: Pick; let commandDetection: CommandDetectionCapability; let commandService: TestCommandService; let openerService: OpenerService; @@ -65,9 +63,6 @@ suite('QuickFixAddon', () => { instantiationService.stub(IContextMenuService, instantiationService.createInstance(ContextMenuService)); instantiationService.stub(IOpenerService, {} as Partial); commandService = new TestCommandService(instantiationService); - terminalInstance = { - async freePortKillProcess(port: string): Promise { } - } as Pick; quickFixAddon = instantiationService.createInstance(TerminalQuickFixAddon, [], capabilities); terminal.loadAddon(quickFixAddon); @@ -212,7 +207,7 @@ suite('QuickFixAddon', () => { enabled: true }]; setup(() => { - const command = freePort(terminalInstance); + const command = freePort(() => Promise.resolve()); expectedMap.set(command.commandLineMatcher.toString(), [command]); quickFixAddon.registerCommandFinishedListener(command); }); From f4b78696aff97376be764f67663d4a01a92fa39d Mon Sep 17 00:00:00 2001 From: Joyce Er Date: Mon, 21 Aug 2023 11:15:17 -0700 Subject: [PATCH 059/221] Include followups when transferring Quick Chat --- src/vs/workbench/contrib/chat/browser/chatQuick.ts | 3 ++- src/vs/workbench/contrib/chat/common/chatService.ts | 1 + src/vs/workbench/contrib/chat/common/chatServiceImpl.ts | 4 ++++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/chat/browser/chatQuick.ts b/src/vs/workbench/contrib/chat/browser/chatQuick.ts index e23c698298e..9851fa5a954 100644 --- a/src/vs/workbench/contrib/chat/browser/chatQuick.ts +++ b/src/vs/workbench/contrib/chat/browser/chatQuick.ts @@ -186,7 +186,8 @@ class QuickChat extends Disposable { request.message as string, { message: request.response.response.asString(), - errorDetails: request.response.errorDetails + errorDetails: request.response.errorDetails, + followups: request.response.followups }); } else if (request.message) { diff --git a/src/vs/workbench/contrib/chat/common/chatService.ts b/src/vs/workbench/contrib/chat/common/chatService.ts index 70f6c3f780f..040bee23cae 100644 --- a/src/vs/workbench/contrib/chat/common/chatService.ts +++ b/src/vs/workbench/contrib/chat/common/chatService.ts @@ -178,6 +178,7 @@ export interface IChatDynamicRequest { export interface IChatCompleteResponse { message: string; errorDetails?: IChatResponseErrorDetails; + followups?: IChatFollowup[]; } export interface IChatDetail { diff --git a/src/vs/workbench/contrib/chat/common/chatServiceImpl.ts b/src/vs/workbench/contrib/chat/common/chatServiceImpl.ts index a8663c161df..cbc2a2ddff8 100644 --- a/src/vs/workbench/contrib/chat/common/chatServiceImpl.ts +++ b/src/vs/workbench/contrib/chat/common/chatServiceImpl.ts @@ -669,6 +669,10 @@ export class ChatService extends Disposable implements IChatService { session: model.session!, errorDetails: response.errorDetails, }); + if (response.followups !== undefined) { + model.setFollowups(request, response.followups); + } + model.completeResponse(request); } cancelCurrentRequestForSession(sessionId: string): void { From 2e0609686a2791f5f850301dbd504534ae27a508 Mon Sep 17 00:00:00 2001 From: Joyce Er Date: Mon, 21 Aug 2023 11:44:41 -0700 Subject: [PATCH 060/221] Transfer file trees from quick chat to panel chat --- .../workbench/api/browser/mainThreadChat.ts | 7 +++--- .../contrib/chat/browser/chatQuick.ts | 2 +- .../contrib/chat/common/chatModel.ts | 22 ++++++++++++------- .../contrib/chat/common/chatService.ts | 5 +++-- .../contrib/chat/common/chatServiceImpl.ts | 16 ++++++++++---- 5 files changed, 34 insertions(+), 18 deletions(-) diff --git a/src/vs/workbench/api/browser/mainThreadChat.ts b/src/vs/workbench/api/browser/mainThreadChat.ts index b0621471f66..ddeba6f997b 100644 --- a/src/vs/workbench/api/browser/mainThreadChat.ts +++ b/src/vs/workbench/api/browser/mainThreadChat.ts @@ -11,6 +11,7 @@ import { URI, UriComponents } from 'vs/base/common/uri'; import { ExtHostChatShape, ExtHostContext, IChatRequestDto, IChatResponseProgressDto, MainContext, MainThreadChatShape } from 'vs/workbench/api/common/extHost.protocol'; import { IChatWidgetService } from 'vs/workbench/contrib/chat/browser/chat'; import { IChatContributionService } from 'vs/workbench/contrib/chat/common/chatContributionService'; +import { isCompleteInteractiveProgressTreeData } from 'vs/workbench/contrib/chat/common/chatModel'; import { IChat, IChatDynamicRequest, IChatProgress, IChatRequest, IChatResponse, IChatResponseProgressFileTreeData, IChatService } from 'vs/workbench/contrib/chat/common/chatService'; import { IExtHostContext, extHostNamedCustomer } from 'vs/workbench/services/extensions/common/extHostCustomers'; @@ -141,7 +142,7 @@ export class MainThreadChat extends Disposable implements MainThreadChatShape { // Complete an existing deferred promise with resolved content const responsePartId = `${id}_${responsePartHandle}`; const deferredContentPromise = this._activeResponsePartPromises.get(responsePartId); - if (deferredContentPromise && 'treeData' in progress) { + if (deferredContentPromise && isCompleteInteractiveProgressTreeData(progress)) { const withRevivedUris = revive<{ treeData: IChatResponseProgressFileTreeData }>(progress); deferredContentPromise.complete(withRevivedUris); this._activeResponsePartPromises.delete(responsePartId); @@ -152,8 +153,8 @@ export class MainThreadChat extends Disposable implements MainThreadChatShape { return; } - // No need to support standalone tree data that's not attached to a placeholder - if ('treeData' in progress) { + // No need to support standalone tree data that's not attached to a placeholder in API + if (isCompleteInteractiveProgressTreeData(progress)) { return; } diff --git a/src/vs/workbench/contrib/chat/browser/chatQuick.ts b/src/vs/workbench/contrib/chat/browser/chatQuick.ts index 9851fa5a954..6e30b77907b 100644 --- a/src/vs/workbench/contrib/chat/browser/chatQuick.ts +++ b/src/vs/workbench/contrib/chat/browser/chatQuick.ts @@ -185,7 +185,7 @@ class QuickChat extends Disposable { this.chatService.addCompleteRequest(widget.viewModel.sessionId, request.message as string, { - message: request.response.response.asString(), + message: request.response.response.value, errorDetails: request.response.errorDetails, followups: request.response.followups }); diff --git a/src/vs/workbench/contrib/chat/common/chatModel.ts b/src/vs/workbench/contrib/chat/common/chatModel.ts index a242829fd92..87b7ef10cc6 100644 --- a/src/vs/workbench/contrib/chat/common/chatModel.ts +++ b/src/vs/workbench/contrib/chat/common/chatModel.ts @@ -25,7 +25,7 @@ export interface IChatRequestModel { export interface IResponse { readonly value: (IMarkdownString | IChatResponseProgressFileTreeData)[]; onDidChangeValue: Event; - updateContent(responsePart: string | { placeholder: string; resolvedContent?: Promise }, quiet?: boolean): void; + updateContent(responsePart: string | { treeData: IChatResponseProgressFileTreeData } | { placeholder: string; resolvedContent?: Promise }, quiet?: boolean): void; asString(): string; } @@ -111,7 +111,7 @@ export class Response implements IResponse { this._responseData = Array.isArray(value) ? value : [value]; this._responseParts = Array.isArray(value) ? value.map((v) => ('value' in v ? { string: v } : { treeData: v })) : [{ string: value }]; this._responseRepr = this._responseParts.map((part) => { - if ('treeData' in part) { + if (isCompleteInteractiveProgressTreeData(part)) { return ''; } return part.string.value; @@ -122,12 +122,12 @@ export class Response implements IResponse { return this._responseRepr; } - updateContent(responsePart: string | { placeholder: string; resolvedContent?: Promise }, quiet?: boolean): void { + updateContent(responsePart: string | { treeData: IChatResponseProgressFileTreeData } | { placeholder: string; resolvedContent?: Promise }, quiet?: boolean): void { if (typeof responsePart === 'string') { const responsePartLength = this._responseParts.length - 1; const lastResponsePart = this._responseParts[responsePartLength]; - if (lastResponsePart.resolving === true || 'treeData' in lastResponsePart) { + if (lastResponsePart.resolving === true || isCompleteInteractiveProgressTreeData(lastResponsePart)) { // The last part is resolving or a tree data item, start a new part this._responseParts.push({ string: new MarkdownString(responsePart) }); } else { @@ -151,19 +151,21 @@ export class Response implements IResponse { this._updateRepr(quiet); } }); + } else if (isCompleteInteractiveProgressTreeData(responsePart)) { + this._responseParts.push(responsePart); } } private _updateRepr(quiet?: boolean) { this._responseData = this._responseParts.map(part => { - if ('treeData' in part) { + if (isCompleteInteractiveProgressTreeData(part)) { return part.treeData; } return part.string; }); this._responseRepr = this._responseParts.map(part => { - if ('treeData' in part) { + if (isCompleteInteractiveProgressTreeData(part)) { return ''; } return part.string.value; @@ -243,7 +245,7 @@ export class ChatResponseModel extends Disposable implements IChatResponseModel this._id = 'response_' + ChatResponseModel.nextId++; } - updateContent(responsePart: string | { placeholder: string; resolvedContent?: Promise }, quiet?: boolean) { + updateContent(responsePart: string | { treeData: IChatResponseProgressFileTreeData } | { placeholder: string; resolvedContent?: Promise }, quiet?: boolean) { this._response.updateContent(responsePart, quiet); } @@ -547,7 +549,7 @@ export class ChatModel extends Disposable implements IChatModel { if ('content' in progress) { request.response.updateContent(progress.content, quiet); - } else if ('placeholder' in progress) { + } else if ('placeholder' in progress || isCompleteInteractiveProgressTreeData(progress)) { request.response.updateContent(progress, quiet); } else { request.setProviderRequestId(progress.requestId); @@ -692,3 +694,7 @@ export class ChatWelcomeMessageModel implements IChatWelcomeMessageModel { return this.session.responderAvatarIconUri; } } + +export function isCompleteInteractiveProgressTreeData(item: unknown): item is { treeData: IChatResponseProgressFileTreeData } { + return typeof item === 'object' && !!item && 'treeData' in item; +} diff --git a/src/vs/workbench/contrib/chat/common/chatService.ts b/src/vs/workbench/contrib/chat/common/chatService.ts index 040bee23cae..be769ba4f10 100644 --- a/src/vs/workbench/contrib/chat/common/chatService.ts +++ b/src/vs/workbench/contrib/chat/common/chatService.ts @@ -5,6 +5,7 @@ import { CancellationToken } from 'vs/base/common/cancellation'; import { Event } from 'vs/base/common/event'; +import { IMarkdownString } from 'vs/base/common/htmlContent'; import { IDisposable } from 'vs/base/common/lifecycle'; import { URI } from 'vs/base/common/uri'; import { ProviderResult } from 'vs/editor/common/languages'; @@ -51,7 +52,7 @@ export interface IChatResponseProgressFileTreeData { } export type IChatProgress = - { content: string } | { requestId: string } | { placeholder: string; resolvedContent: Promise }; + { content: string } | { requestId: string } | { treeData: IChatResponseProgressFileTreeData } | { placeholder: string; resolvedContent: Promise }; export interface IPersistedChatState { } export interface IChatProvider { @@ -176,7 +177,7 @@ export interface IChatDynamicRequest { } export interface IChatCompleteResponse { - message: string; + message: string | (IMarkdownString | IChatResponseProgressFileTreeData)[]; errorDetails?: IChatResponseErrorDetails; followups?: IChatFollowup[]; } diff --git a/src/vs/workbench/contrib/chat/common/chatServiceImpl.ts b/src/vs/workbench/contrib/chat/common/chatServiceImpl.ts index cbc2a2ddff8..ae621f87f69 100644 --- a/src/vs/workbench/contrib/chat/common/chatServiceImpl.ts +++ b/src/vs/workbench/contrib/chat/common/chatServiceImpl.ts @@ -22,7 +22,7 @@ import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storag import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { CONTEXT_PROVIDER_EXISTS } from 'vs/workbench/contrib/chat/common/chatContextKeys'; -import { ChatModel, ChatWelcomeMessageModel, IChatModel, ISerializableChatData, ISerializableChatsData } from 'vs/workbench/contrib/chat/common/chatModel'; +import { ChatModel, ChatWelcomeMessageModel, IChatModel, ISerializableChatData, ISerializableChatsData, isCompleteInteractiveProgressTreeData } from 'vs/workbench/contrib/chat/common/chatModel'; import { ChatMessageRole, IChatMessage } from 'vs/workbench/contrib/chat/common/chatProvider'; import { IChat, IChatCompleteResponse, IChatDetail, IChatDynamicRequest, IChatProgress, IChatProvider, IChatProviderInfo, IChatReplyFollowup, IChatRequest, IChatResponse, IChatService, IChatTransferredSessionData, IChatUserActionEvent, ISlashCommand, InteractiveSessionCopyKind, InteractiveSessionVoteDirection } from 'vs/workbench/contrib/chat/common/chatService'; import { IChatSlashCommandService, IChatSlashFragment } from 'vs/workbench/contrib/chat/common/chatSlashCommands'; @@ -453,6 +453,9 @@ export class ChatService extends Disposable implements IChatService { this.trace('sendRequest', `Provider returned progress for session ${model.sessionId}, ${progress.content.length} chars`); } else if ('placeholder' in progress) { this.trace('sendRequest', `Provider returned placeholder for session ${model.sessionId}, ${progress.placeholder}`); + } else if (isCompleteInteractiveProgressTreeData(progress)) { + // This isn't exposed in API + this.trace('sendRequest', `Provider returned tree data for session ${model.sessionId}, ${progress.treeData.label}`); } else { this.trace('sendRequest', `Provider returned id for session ${model.sessionId}, ${progress.requestId}`); } @@ -662,9 +665,14 @@ export class ChatService extends Disposable implements IChatService { await model.waitForInitialization(); const request = model.addRequest(message); - model.acceptResponseProgress(request, { - content: response.message, - }, true); + if (typeof response.message === 'string') { + model.acceptResponseProgress(request, { content: response.message }); + } else { + for (const part of response.message) { + const progress = isMarkdownString(part) ? { content: part.value } : { treeData: part }; + model.acceptResponseProgress(request, progress, true); + } + } model.setResponse(request, { session: model.session!, errorDetails: response.errorDetails, From 7a5894a5270b8131afd05efaee78160f346c2a63 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 21 Aug 2023 21:05:35 +0200 Subject: [PATCH 061/221] voice - actions tweaks --- src/vs/workbench/contrib/chat/browser/chat.ts | 3 +- .../contrib/chat/browser/chatQuick.ts | 11 ++++- .../actions/chatVoiceInputActions.ts | 47 ++++++++++++++----- 3 files changed, 46 insertions(+), 15 deletions(-) diff --git a/src/vs/workbench/contrib/chat/browser/chat.ts b/src/vs/workbench/contrib/chat/browser/chat.ts index 7450fb52efa..2950dd6579b 100644 --- a/src/vs/workbench/contrib/chat/browser/chat.ts +++ b/src/vs/workbench/contrib/chat/browser/chat.ts @@ -35,7 +35,8 @@ export interface IChatWidgetService { export interface IQuickChatService { readonly _serviceBrand: undefined; - enabled: boolean; + readonly onDidClose: Event; + readonly enabled: boolean; toggle(providerId?: string, query?: string): void; focus(): void; open(): void; diff --git a/src/vs/workbench/contrib/chat/browser/chatQuick.ts b/src/vs/workbench/contrib/chat/browser/chatQuick.ts index 20b6076bb0c..e75116f1551 100644 --- a/src/vs/workbench/contrib/chat/browser/chatQuick.ts +++ b/src/vs/workbench/contrib/chat/browser/chatQuick.ts @@ -5,6 +5,7 @@ import * as dom from 'vs/base/browser/dom'; import { CancellationToken } from 'vs/base/common/cancellation'; +import { Emitter } from 'vs/base/common/event'; import { Disposable, DisposableStore } from 'vs/base/common/lifecycle'; import { IContextKeyService, IScopedContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; @@ -17,9 +18,12 @@ import { ChatWidget } from 'vs/workbench/contrib/chat/browser/chatWidget'; import { ChatModel } from 'vs/workbench/contrib/chat/common/chatModel'; import { IChatService } from 'vs/workbench/contrib/chat/common/chatService'; -export class QuickChatService implements IQuickChatService { +export class QuickChatService extends Disposable implements IQuickChatService { readonly _serviceBrand: undefined; + private readonly _onDidClose = this._register(new Emitter()); + readonly onDidClose = this._onDidClose.event; + private _input: IQuickWidget | undefined; private _currentChat: QuickChat | undefined; @@ -27,7 +31,9 @@ export class QuickChatService implements IQuickChatService { @IQuickInputService private readonly quickInputService: IQuickInputService, @IChatService private readonly chatService: IChatService, @IInstantiationService private readonly instantiationService: IInstantiationService, - ) { } + ) { + super(); + } get enabled(): boolean { return this.chatService.getProviderInfos().length > 0; @@ -84,6 +90,7 @@ export class QuickChatService implements IQuickChatService { disposableStore.add(this._input.onDidHide(() => { disposableStore.dispose(); this._input = undefined; + this._onDidClose.fire(); })); this._currentChat.focus(); diff --git a/src/vs/workbench/contrib/chat/electron-sandbox/actions/chatVoiceInputActions.ts b/src/vs/workbench/contrib/chat/electron-sandbox/actions/chatVoiceInputActions.ts index 9e3058c7405..2ebbbb79bf0 100644 --- a/src/vs/workbench/contrib/chat/electron-sandbox/actions/chatVoiceInputActions.ts +++ b/src/vs/workbench/contrib/chat/electron-sandbox/actions/chatVoiceInputActions.ts @@ -3,9 +3,11 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { Event } from 'vs/base/common/event'; +import { firstOrDefault } from 'vs/base/common/arrays'; import { CancellationTokenSource } from 'vs/base/common/cancellation'; import { Codicon } from 'vs/base/common/codicons'; -import { DisposableStore, toDisposable } from 'vs/base/common/lifecycle'; +import { DisposableStore, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { equalsIgnoreCase } from 'vs/base/common/strings'; import { ServicesAccessor } from 'vs/editor/browser/editorExtensions'; import { localize } from 'vs/nls'; @@ -15,6 +17,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { spinningLoading } from 'vs/platform/theme/common/iconRegistry'; import { CHAT_CATEGORY } from 'vs/workbench/contrib/chat/browser/actions/chatActions'; import { IChatWidget, IChatWidgetService, IQuickChatService } from 'vs/workbench/contrib/chat/browser/chat'; +import { IChatService } from 'vs/workbench/contrib/chat/common/chatService'; import { IWorkbenchVoiceRecognitionService } from 'vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService'; const CONTEXT_CHAT_VOICE_INPUT_GETTING_READY = new RawContextKey('chatVoiceInputGettingReady', false, { type: 'boolean', description: localize('chatVoiceInputGettingReady', "True when there is voice input for chat getting ready.") }); @@ -50,11 +53,14 @@ class ChatVoiceInputSession { @IWorkbenchVoiceRecognitionService private readonly voiceRecognitionService: IWorkbenchVoiceRecognitionService ) { } - async start(context: IChatVoiceInputActionContext): Promise { + async start(context: IChatVoiceInputActionContext, disposables?: IDisposable[]): Promise { this.stop(); this.chatVoiceInputGettingReadyKey.set(true); this.currentChatVoiceInputSession = new DisposableStore(); + for (const disposable of disposables ?? []) { + this.currentChatVoiceInputSession.add(disposable); + } const cts = new CancellationTokenSource(); this.currentChatVoiceInputSession.add(toDisposable(() => cts.dispose(true))); @@ -108,6 +114,7 @@ class ChatVoiceInputSession { } class StartChatVoiceInputAction extends Action2 { + static readonly ID = 'workbench.action.chat.startVoiceInput'; constructor() { @@ -118,6 +125,7 @@ class StartChatVoiceInputAction extends Action2 { original: 'Start Voice Input' }, category: CHAT_CATEGORY, + f1: true, icon: Codicon.record, precondition: CONTEXT_CHAT_VOICE_INPUT_GETTING_READY.negate(), menu: { @@ -129,23 +137,33 @@ class StartChatVoiceInputAction extends Action2 { }); } - run(accessor: ServicesAccessor, ...args: any[]): void { + async run(accessor: ServicesAccessor, ...args: any[]): Promise { const chatWidgetService = accessor.get(IChatWidgetService); + const chatService = accessor.get(IChatService); + const instantiationService = accessor.get(IInstantiationService); let context = args[0]; if (!isVoiceInputActionContext(context)) { if (chatWidgetService.lastFocusedWidget?.hasInputFocus()) { context = { widget: chatWidgetService.lastFocusedWidget }; } else { - return; + const provider = firstOrDefault(chatService.getProviderInfos()); + if (provider) { + context = { widget: await chatWidgetService.revealViewForProvider(provider.id) }; + } } } - ChatVoiceInputSession.getInstance(accessor.get(IInstantiationService)).start(context); + if (!isVoiceInputActionContext(context)) { + return; + } + + ChatVoiceInputSession.getInstance(instantiationService).start(context); } } class StopChatVoiceInputAction extends Action2 { + static readonly ID = 'workbench.action.chat.stopVoiceInput'; constructor() { @@ -173,15 +191,16 @@ class StopChatVoiceInputAction extends Action2 { } } -class StartVoiceQuickChatAction extends Action2 { - static readonly ID = 'workbench.action.chat.startVoiceQuickChat'; +class VoiceQuickChatAction extends Action2 { + + static readonly ID = 'workbench.action.chat.voiceQuickChat'; constructor() { super({ - id: StartVoiceQuickChatAction.ID, + id: VoiceQuickChatAction.ID, title: { - value: localize('interactive.startVoiceChat.label', "Start Voice Quick Chat"), - original: 'Start Voice Quick Chat' + value: localize('interactive.voiceQuickChat.label', "Quick Chat with Voice Input"), + original: 'Quick Chat with Voice Input' }, category: CHAT_CATEGORY, f1: true @@ -191,12 +210,16 @@ class StartVoiceQuickChatAction extends Action2 { run(accessor: ServicesAccessor): void { const quickChatService = accessor.get(IQuickChatService); const chatWidgetService = accessor.get(IChatWidgetService); + const instantiationService = accessor.get(IInstantiationService); quickChatService.open(); + const disposables: IDisposable[] = []; + Event.once(quickChatService.onDidClose)(() => ChatVoiceInputSession.getInstance(instantiationService).stop(), undefined, disposables); + const widget = chatWidgetService.lastFocusedWidget; if (widget) { - ChatVoiceInputSession.getInstance(accessor.get(IInstantiationService)).start({ widget }); + ChatVoiceInputSession.getInstance(accessor.get(IInstantiationService)).start({ widget }, disposables); } } } @@ -204,5 +227,5 @@ class StartVoiceQuickChatAction extends Action2 { export function registerChatVoiceInputActions() { registerAction2(StartChatVoiceInputAction); registerAction2(StopChatVoiceInputAction); - registerAction2(StartVoiceQuickChatAction); + registerAction2(VoiceQuickChatAction); } From 41cb0fc5647a171b40a89c1e1ceb5e65913132ec Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 22 Aug 2023 06:45:00 +0200 Subject: [PATCH 062/221] voice - reduce audio buffer delay --- .../electron-sandbox/voiceTranscriptionWorklet.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/services/voiceRecognition/electron-sandbox/voiceTranscriptionWorklet.ts b/src/vs/workbench/services/voiceRecognition/electron-sandbox/voiceTranscriptionWorklet.ts index a298b23b29d..47c7baf3433 100644 --- a/src/vs/workbench/services/voiceRecognition/electron-sandbox/voiceTranscriptionWorklet.ts +++ b/src/vs/workbench/services/voiceRecognition/electron-sandbox/voiceTranscriptionWorklet.ts @@ -12,7 +12,7 @@ declare class AudioWorkletProcessor { class VoiceTranscriptionWorklet extends AudioWorkletProcessor { - private static readonly BUFFER_TIMESPAN = 2000; + private static readonly BUFFER_TIMESPAN = 1000; private startTime: number | undefined = undefined; private stopped: boolean = false; From 32c476a056ff665fa96d9325a01eb84323acb3cb Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Tue, 22 Aug 2023 09:31:25 +0200 Subject: [PATCH 063/221] adding a comment right above the setting --- .../src/configuration/configuration.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/extensions/typescript-language-features/src/configuration/configuration.ts b/extensions/typescript-language-features/src/configuration/configuration.ts index 2650d015d88..23b1ee8b466 100644 --- a/extensions/typescript-language-features/src/configuration/configuration.ts +++ b/extensions/typescript-language-features/src/configuration/configuration.ts @@ -200,6 +200,7 @@ export abstract class BaseServiceConfigurationProvider implements ServiceConfigu } protected readEnableDiagnosticsTelemetry(configuration: vscode.WorkspaceConfiguration): boolean { + /** This setting does not appear in the settings view, as it is not to be enabled by users outside the team */ return configuration.get('typescript.enableDiagnosticsTelemetry', false); } From df5bf004f46fad28759643b047fdfd638058cba1 Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Tue, 22 Aug 2023 09:33:41 +0200 Subject: [PATCH 064/221] checking also that the file is of type typescriptreact --- .../src/languageFeatures/diagnostics.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts b/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts index 80093b4701c..5dbdf3f350d 100644 --- a/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts +++ b/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts @@ -163,7 +163,7 @@ class DiagnosticsTelemetryManager extends Disposable { ) { super(); this._register(vscode.workspace.onDidChangeTextDocument(e => { - if (e.document.languageId === 'typescript') { + if (e.document.languageId === 'typescript' || e.document.languageId === 'typescriptreact') { this._updateAllDiagnosticCodesAfterTimeout(); } })); From 46ca479aa391b35b39cc11900f21f549dd94f3e9 Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Tue, 22 Aug 2023 09:42:12 +0200 Subject: [PATCH 065/221] using a resource map now, need to normalize to a string? --- .../src/languageFeatures/diagnostics.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts b/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts index 5dbdf3f350d..e031a7b6061 100644 --- a/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts +++ b/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts @@ -154,7 +154,7 @@ class DiagnosticSettings { class DiagnosticsTelemetryManager extends Disposable { private readonly _diagnosticCodesMap = new Map(); - private readonly _diagnosticSnapshotsMap = new Map(); + private readonly _diagnosticSnapshotsMap = new ResourceMap(uri => uri.toString(), { onCaseInsensitiveFileSystem: false }); private _timeout: NodeJS.Timeout | undefined; constructor( @@ -185,9 +185,8 @@ class DiagnosticsTelemetryManager extends Disposable { private _updateDiagnosticCodes() { this._diagnosticsCollection.forEach((uri, diagnostics) => { - const uriString = uri.toString(); - const previousDiagnostics = this._diagnosticSnapshotsMap.get(uriString); - this._diagnosticSnapshotsMap.set(uriString, diagnostics); + const previousDiagnostics = this._diagnosticSnapshotsMap.get(uri); + this._diagnosticSnapshotsMap.set(uri, diagnostics); const diagnosticsDiff = diagnostics.filter((diagnostic) => !previousDiagnostics?.some((previousDiagnostic) => equals(diagnostic, previousDiagnostic))); diagnosticsDiff.forEach((diagnostic) => { const code = diagnostic.code; From 82cbf90600daea047c9153a638f01b42d670f939 Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Tue, 22 Aug 2023 09:43:11 +0200 Subject: [PATCH 066/221] clearing the timeout on dispose of the class --- .../src/languageFeatures/diagnostics.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts b/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts index e031a7b6061..a2a889d1ba2 100644 --- a/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts +++ b/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts @@ -218,6 +218,11 @@ class DiagnosticsTelemetryManager extends Disposable { } }, 5 * 60 * 1000); // 5 minutes } + + override dispose() { + super.dispose(); + clearTimeout(this._timeout); + } } export class DiagnosticsManager extends Disposable { From d8affc039ab669c3009aad5bab4e8e2f9de299a9 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Tue, 22 Aug 2023 12:34:24 +0200 Subject: [PATCH 067/221] fix #188582 (#190957) --- .../common/extensionsProfileScannerService.ts | 19 +- .../extensionsProfileScannerService.test.ts | 252 +++++++++++++++++- 2 files changed, 259 insertions(+), 12 deletions(-) diff --git a/src/vs/platform/extensionManagement/common/extensionsProfileScannerService.ts b/src/vs/platform/extensionManagement/common/extensionsProfileScannerService.ts index 30e749ac312..40eb2584305 100644 --- a/src/vs/platform/extensionManagement/common/extensionsProfileScannerService.ts +++ b/src/vs/platform/extensionManagement/common/extensionsProfileScannerService.ts @@ -124,22 +124,24 @@ export abstract class AbstractExtensionsProfileScannerService extends Disposable const extensionsToRemove: IScannedProfileExtension[] = []; const extensionsToAdd: IScannedProfileExtension[] = []; try { - await this.withProfileExtensions(profileLocation, profileExtensions => { + await this.withProfileExtensions(profileLocation, existingExtensions => { const result: IScannedProfileExtension[] = []; - for (const extension of profileExtensions) { - if (extensions.some(([e]) => areSameExtensions(e.identifier, extension.identifier) && e.manifest.version !== extension.version)) { + for (const existing of existingExtensions) { + if (extensions.some(([e]) => areSameExtensions(e.identifier, existing.identifier) && e.manifest.version !== existing.version)) { // Remove the existing extension with different version - extensionsToRemove.push(extension); + extensionsToRemove.push(existing); } else { - result.push(extension); + result.push(existing); } } for (const [extension, metadata] of extensions) { - if (!result.some(e => areSameExtensions(e.identifier, extension.identifier) && e.version === extension.manifest.version)) { - // Add only if the same version of the extension is not already added - const extensionToAdd = { identifier: extension.identifier, version: extension.manifest.version, location: extension.location, metadata }; + const index = result.findIndex(e => areSameExtensions(e.identifier, extension.identifier) && e.version === extension.manifest.version); + const extensionToAdd = { identifier: extension.identifier, version: extension.manifest.version, location: extension.location, metadata }; + if (index === -1) { extensionsToAdd.push(extensionToAdd); result.push(extensionToAdd); + } else { + result.splice(index, 1, extensionToAdd); } } if (extensionsToAdd.length) { @@ -189,7 +191,6 @@ export abstract class AbstractExtensionsProfileScannerService extends Disposable async removeExtensionFromProfile(extension: IExtension, profileLocation: URI): Promise { const extensionsToRemove: IScannedProfileExtension[] = []; - this._onRemoveExtensions.fire({ extensions: extensionsToRemove, profileLocation }); try { await this.withProfileExtensions(profileLocation, profileExtensions => { const result: IScannedProfileExtension[] = []; diff --git a/src/vs/platform/extensionManagement/test/common/extensionsProfileScannerService.test.ts b/src/vs/platform/extensionManagement/test/common/extensionsProfileScannerService.test.ts index 2dcd920d3e2..b2fa0668e72 100644 --- a/src/vs/platform/extensionManagement/test/common/extensionsProfileScannerService.test.ts +++ b/src/vs/platform/extensionManagement/test/common/extensionsProfileScannerService.test.ts @@ -4,13 +4,14 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; +import * as sinon from 'sinon'; import { VSBuffer } from 'vs/base/common/buffer'; import { DisposableStore } from 'vs/base/common/lifecycle'; import { joinPath } from 'vs/base/common/resources'; import { URI } from 'vs/base/common/uri'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; -import { AbstractExtensionsProfileScannerService } from 'vs/platform/extensionManagement/common/extensionsProfileScannerService'; -import { ExtensionType, IExtension, TargetPlatform } from 'vs/platform/extensions/common/extensions'; +import { AbstractExtensionsProfileScannerService, ProfileExtensionsEvent } from 'vs/platform/extensionManagement/common/extensionsProfileScannerService'; +import { ExtensionType, IExtension, IExtensionManifest, TargetPlatform } from 'vs/platform/extensions/common/extensions'; import { FileService } from 'vs/platform/files/common/fileService'; import { IFileService } from 'vs/platform/files/common/files'; import { InMemoryFileSystemProvider } from 'vs/platform/files/common/inMemoryFilesystemProvider'; @@ -47,6 +48,10 @@ suite('ExtensionsProfileScannerService', () => { instantiationService.stub(IUserDataProfilesService, userDataProfilesService); }); + teardown(() => disposables.clear()); + + suiteTeardown(() => sinon.restore()); + test('write extensions located in the same extensions folder', async () => { const testObject = instantiationService.createInstance(TestObject, extensionsLocation); @@ -442,7 +447,247 @@ suite('ExtensionsProfileScannerService', () => { assert.deepStrictEqual(manifestContent, [{ identifier: extension.identifier, location: extension.location.toJSON(), relativeLocation: 'pub.a-1.0.0', version: extension.manifest.version }]); }); - function aExtension(id: string, location: URI, e?: Partial): IExtension { + test('add extension trigger events', async () => { + const testObject = instantiationService.createInstance(TestObject, extensionsLocation); + const target1 = sinon.stub(); + const target2 = sinon.stub(); + testObject.onAddExtensions(target1); + testObject.onDidAddExtensions(target2); + + const extensionsManifest = joinPath(extensionsLocation, 'extensions.json'); + const extension = aExtension('pub.a', joinPath(ROOT, 'foo', 'pub.a-1.0.0')); + await testObject.addExtensionsToProfile([[extension, undefined]], extensionsManifest); + + const actual = await testObject.scanProfileExtensions(extensionsManifest); + assert.deepStrictEqual(actual.map(a => ({ ...a, location: a.location.toJSON() })), [{ identifier: extension.identifier, location: extension.location.toJSON(), version: extension.manifest.version, metadata: undefined }]); + + assert.ok(target1.calledOnce); + assert.deepStrictEqual(((target1.args[0][0])).profileLocation.toString(), extensionsManifest.toString()); + assert.deepStrictEqual(((target1.args[0][0])).extensions.length, 1); + assert.deepStrictEqual(((target1.args[0][0])).extensions[0].identifier, extension.identifier); + assert.deepStrictEqual(((target1.args[0][0])).extensions[0].version, extension.manifest.version); + assert.deepStrictEqual(((target1.args[0][0])).extensions[0].location.toString(), extension.location.toString()); + + assert.ok(target2.calledOnce); + assert.deepStrictEqual(((target2.args[0][0])).profileLocation.toString(), extensionsManifest.toString()); + assert.deepStrictEqual(((target2.args[0][0])).extensions.length, 1); + assert.deepStrictEqual(((target2.args[0][0])).extensions[0].identifier, extension.identifier); + assert.deepStrictEqual(((target2.args[0][0])).extensions[0].version, extension.manifest.version); + assert.deepStrictEqual(((target2.args[0][0])).extensions[0].location.toString(), extension.location.toString()); + }); + + test('remove extension trigger events', async () => { + const testObject = instantiationService.createInstance(TestObject, extensionsLocation); + const target1 = sinon.stub(); + const target2 = sinon.stub(); + testObject.onRemoveExtensions(target1); + testObject.onDidRemoveExtensions(target2); + + const extensionsManifest = joinPath(extensionsLocation, 'extensions.json'); + const extension = aExtension('pub.a', joinPath(ROOT, 'foo', 'pub.a-1.0.0')); + await testObject.addExtensionsToProfile([[extension, undefined]], extensionsManifest); + await testObject.removeExtensionFromProfile(extension, extensionsManifest); + + const actual = await testObject.scanProfileExtensions(extensionsManifest); + assert.deepStrictEqual(actual.length, 0); + + assert.ok(target1.calledOnce); + assert.deepStrictEqual(((target1.args[0][0])).profileLocation.toString(), extensionsManifest.toString()); + assert.deepStrictEqual(((target1.args[0][0])).extensions.length, 1); + assert.deepStrictEqual(((target1.args[0][0])).extensions[0].identifier, extension.identifier); + assert.deepStrictEqual(((target1.args[0][0])).extensions[0].version, extension.manifest.version); + assert.deepStrictEqual(((target1.args[0][0])).extensions[0].location.toString(), extension.location.toString()); + + assert.ok(target2.calledOnce); + assert.deepStrictEqual(((target2.args[0][0])).profileLocation.toString(), extensionsManifest.toString()); + assert.deepStrictEqual(((target2.args[0][0])).extensions.length, 1); + assert.deepStrictEqual(((target2.args[0][0])).extensions[0].identifier, extension.identifier); + assert.deepStrictEqual(((target2.args[0][0])).extensions[0].version, extension.manifest.version); + assert.deepStrictEqual(((target2.args[0][0])).extensions[0].location.toString(), extension.location.toString()); + }); + + test('add extension with same id but different version', async () => { + const testObject = instantiationService.createInstance(TestObject, extensionsLocation); + + const extensionsManifest = joinPath(extensionsLocation, 'extensions.json'); + + const extension1 = aExtension('pub.a', joinPath(ROOT, 'pub.a-1.0.0')); + await testObject.addExtensionsToProfile([[extension1, undefined]], extensionsManifest); + + const target1 = sinon.stub(); + const target2 = sinon.stub(); + const target3 = sinon.stub(); + const target4 = sinon.stub(); + testObject.onAddExtensions(target1); + testObject.onRemoveExtensions(target2); + testObject.onDidAddExtensions(target3); + testObject.onDidRemoveExtensions(target4); + const extension2 = aExtension('pub.a', joinPath(ROOT, 'pub.a-2.0.0'), undefined, { version: '2.0.0' }); + await testObject.addExtensionsToProfile([[extension2, undefined]], extensionsManifest); + + const actual = await testObject.scanProfileExtensions(extensionsManifest); + assert.deepStrictEqual(actual.map(a => ({ ...a, location: a.location.toJSON() })), [{ identifier: extension2.identifier, location: extension2.location.toJSON(), version: extension2.manifest.version, metadata: undefined }]); + + assert.ok(target1.calledOnce); + assert.deepStrictEqual(((target1.args[0][0])).profileLocation.toString(), extensionsManifest.toString()); + assert.deepStrictEqual(((target1.args[0][0])).extensions.length, 1); + assert.deepStrictEqual(((target1.args[0][0])).extensions[0].identifier, extension2.identifier); + assert.deepStrictEqual(((target1.args[0][0])).extensions[0].version, extension2.manifest.version); + assert.deepStrictEqual(((target1.args[0][0])).extensions[0].location.toString(), extension2.location.toString()); + + assert.ok(target2.calledOnce); + assert.deepStrictEqual(((target2.args[0][0])).profileLocation.toString(), extensionsManifest.toString()); + assert.deepStrictEqual(((target2.args[0][0])).extensions.length, 1); + assert.deepStrictEqual(((target2.args[0][0])).extensions[0].identifier, extension1.identifier); + assert.deepStrictEqual(((target2.args[0][0])).extensions[0].version, extension1.manifest.version); + assert.deepStrictEqual(((target2.args[0][0])).extensions[0].location.toString(), extension1.location.toString()); + + assert.ok(target3.calledOnce); + assert.deepStrictEqual(((target1.args[0][0])).profileLocation.toString(), extensionsManifest.toString()); + assert.deepStrictEqual(((target1.args[0][0])).extensions.length, 1); + assert.deepStrictEqual(((target1.args[0][0])).extensions[0].identifier, extension2.identifier); + assert.deepStrictEqual(((target1.args[0][0])).extensions[0].version, extension2.manifest.version); + assert.deepStrictEqual(((target1.args[0][0])).extensions[0].location.toString(), extension2.location.toString()); + + assert.ok(target4.calledOnce); + assert.deepStrictEqual(((target2.args[0][0])).profileLocation.toString(), extensionsManifest.toString()); + assert.deepStrictEqual(((target2.args[0][0])).extensions.length, 1); + assert.deepStrictEqual(((target2.args[0][0])).extensions[0].identifier, extension1.identifier); + assert.deepStrictEqual(((target2.args[0][0])).extensions[0].version, extension1.manifest.version); + assert.deepStrictEqual(((target2.args[0][0])).extensions[0].location.toString(), extension1.location.toString()); + }); + + test('add same extension', async () => { + const testObject = instantiationService.createInstance(TestObject, extensionsLocation); + + const extensionsManifest = joinPath(extensionsLocation, 'extensions.json'); + + const extension = aExtension('pub.a', joinPath(ROOT, 'pub.a-1.0.0')); + await testObject.addExtensionsToProfile([[extension, undefined]], extensionsManifest); + + const target1 = sinon.stub(); + const target2 = sinon.stub(); + const target3 = sinon.stub(); + const target4 = sinon.stub(); + testObject.onAddExtensions(target1); + testObject.onRemoveExtensions(target2); + testObject.onDidAddExtensions(target3); + testObject.onDidRemoveExtensions(target4); + await testObject.addExtensionsToProfile([[extension, undefined]], extensionsManifest); + + const actual = await testObject.scanProfileExtensions(extensionsManifest); + assert.deepStrictEqual(actual.map(a => ({ ...a, location: a.location.toJSON() })), [{ identifier: extension.identifier, location: extension.location.toJSON(), version: extension.manifest.version, metadata: undefined }]); + assert.ok(target1.notCalled); + assert.ok(target2.notCalled); + assert.ok(target3.notCalled); + assert.ok(target4.notCalled); + }); + + test('add same extension with different metadata', async () => { + const testObject = instantiationService.createInstance(TestObject, extensionsLocation); + + const extensionsManifest = joinPath(extensionsLocation, 'extensions.json'); + + const extension = aExtension('pub.a', joinPath(ROOT, 'pub.a-1.0.0')); + await testObject.addExtensionsToProfile([[extension, undefined]], extensionsManifest); + + const target1 = sinon.stub(); + const target2 = sinon.stub(); + const target3 = sinon.stub(); + const target4 = sinon.stub(); + testObject.onAddExtensions(target1); + testObject.onRemoveExtensions(target2); + testObject.onDidAddExtensions(target3); + testObject.onDidRemoveExtensions(target4); + await testObject.addExtensionsToProfile([[extension, { isApplicationScoped: true }]], extensionsManifest); + + const actual = await testObject.scanProfileExtensions(extensionsManifest); + assert.deepStrictEqual(actual.map(a => ({ ...a, location: a.location.toJSON(), metadata: a.metadata })), [{ identifier: extension.identifier, location: extension.location.toJSON(), version: extension.manifest.version, metadata: { isApplicationScoped: true } }]); + assert.ok(target1.notCalled); + assert.ok(target2.notCalled); + assert.ok(target3.notCalled); + assert.ok(target4.notCalled); + }); + + test('add extension with different version and metadata', async () => { + const testObject = instantiationService.createInstance(TestObject, extensionsLocation); + + const extensionsManifest = joinPath(extensionsLocation, 'extensions.json'); + + const extension1 = aExtension('pub.a', joinPath(ROOT, 'pub.a-1.0.0')); + await testObject.addExtensionsToProfile([[extension1, undefined]], extensionsManifest); + const extension2 = aExtension('pub.a', joinPath(ROOT, 'pub.a-2.0.0'), undefined, { version: '2.0.0' }); + + const target1 = sinon.stub(); + const target2 = sinon.stub(); + const target3 = sinon.stub(); + const target4 = sinon.stub(); + testObject.onAddExtensions(target1); + testObject.onRemoveExtensions(target2); + testObject.onDidAddExtensions(target3); + testObject.onDidRemoveExtensions(target4); + await testObject.addExtensionsToProfile([[extension2, { isApplicationScoped: true }]], extensionsManifest); + + const actual = await testObject.scanProfileExtensions(extensionsManifest); + assert.deepStrictEqual(actual.map(a => ({ ...a, location: a.location.toJSON(), metadata: a.metadata })), [{ identifier: extension2.identifier, location: extension2.location.toJSON(), version: extension2.manifest.version, metadata: { isApplicationScoped: true } }]); + + assert.ok(target1.calledOnce); + assert.deepStrictEqual(((target1.args[0][0])).profileLocation.toString(), extensionsManifest.toString()); + assert.deepStrictEqual(((target1.args[0][0])).extensions.length, 1); + assert.deepStrictEqual(((target1.args[0][0])).extensions[0].identifier, extension2.identifier); + assert.deepStrictEqual(((target1.args[0][0])).extensions[0].version, extension2.manifest.version); + assert.deepStrictEqual(((target1.args[0][0])).extensions[0].location.toString(), extension2.location.toString()); + + assert.ok(target2.calledOnce); + assert.deepStrictEqual(((target2.args[0][0])).profileLocation.toString(), extensionsManifest.toString()); + assert.deepStrictEqual(((target2.args[0][0])).extensions.length, 1); + assert.deepStrictEqual(((target2.args[0][0])).extensions[0].identifier, extension1.identifier); + assert.deepStrictEqual(((target2.args[0][0])).extensions[0].version, extension1.manifest.version); + assert.deepStrictEqual(((target2.args[0][0])).extensions[0].location.toString(), extension1.location.toString()); + + assert.ok(target3.calledOnce); + assert.deepStrictEqual(((target1.args[0][0])).profileLocation.toString(), extensionsManifest.toString()); + assert.deepStrictEqual(((target1.args[0][0])).extensions.length, 1); + assert.deepStrictEqual(((target1.args[0][0])).extensions[0].identifier, extension2.identifier); + assert.deepStrictEqual(((target1.args[0][0])).extensions[0].version, extension2.manifest.version); + assert.deepStrictEqual(((target1.args[0][0])).extensions[0].location.toString(), extension2.location.toString()); + + assert.ok(target4.calledOnce); + assert.deepStrictEqual(((target2.args[0][0])).profileLocation.toString(), extensionsManifest.toString()); + assert.deepStrictEqual(((target2.args[0][0])).extensions.length, 1); + assert.deepStrictEqual(((target2.args[0][0])).extensions[0].identifier, extension1.identifier); + assert.deepStrictEqual(((target2.args[0][0])).extensions[0].version, extension1.manifest.version); + assert.deepStrictEqual(((target2.args[0][0])).extensions[0].location.toString(), extension1.location.toString()); + }); + + test('add extension with same id and version located in the different folder', async () => { + const testObject = instantiationService.createInstance(TestObject, extensionsLocation); + + const extensionsManifest = joinPath(extensionsLocation, 'extensions.json'); + + let extension = aExtension('pub.a', joinPath(ROOT, 'foo', 'pub.a-1.0.0')); + await testObject.addExtensionsToProfile([[extension, undefined]], extensionsManifest); + + const target1 = sinon.stub(); + const target2 = sinon.stub(); + const target3 = sinon.stub(); + const target4 = sinon.stub(); + testObject.onAddExtensions(target1); + testObject.onRemoveExtensions(target2); + testObject.onDidAddExtensions(target3); + testObject.onDidRemoveExtensions(target4); + extension = aExtension('pub.a', joinPath(ROOT, 'pub.a-1.0.0')); + await testObject.addExtensionsToProfile([[extension, undefined]], extensionsManifest); + + const actual = await testObject.scanProfileExtensions(extensionsManifest); + assert.deepStrictEqual(actual.map(a => ({ ...a, location: a.location.toJSON() })), [{ identifier: extension.identifier, location: extension.location.toJSON(), version: extension.manifest.version, metadata: undefined }]); + assert.ok(target1.notCalled); + assert.ok(target2.notCalled); + assert.ok(target3.notCalled); + assert.ok(target4.notCalled); + }); + + function aExtension(id: string, location: URI, e?: Partial, manifest?: Partial): IExtension { return { identifier: { id }, location, @@ -454,6 +699,7 @@ suite('ExtensionsProfileScannerService', () => { publisher: 'publisher', version: '1.0.0', engines: { vscode: '1.0.0' }, + ...manifest, }, isValid: true, validations: [], From f19d12309511a2053a0a928dbbd0e05365b52b6a Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 22 Aug 2023 12:37:40 +0200 Subject: [PATCH 068/221] status bar - introduce `kind` and adopt (fix #184967) (#190947) * status bar - introduce `kind` and adopt (fix #184967) * adopt for extensions * deprecate colors --- .../lib/stylelint/vscode-known-variables.json | 14 ++- .../api/browser/mainThreadStatusBar.ts | 2 +- .../api/browser/statusBarExtensionPoint.ts | 18 +++- .../parts/editor/accessibilityStatus.ts | 5 +- .../browser/parts/editor/editorStatus.ts | 8 +- .../parts/statusbar/media/statusbarpart.css | 61 ++++++++++-- .../browser/parts/statusbar/statusbarItem.ts | 19 +++- .../browser/parts/statusbar/statusbarPart.ts | 4 +- src/vs/workbench/common/theme.ts | 94 ++++++++++++++++--- .../browser/languageStatus.contribution.ts | 18 ++-- .../editorStatusBar/editorStatusBar.ts | 2 +- .../contrib/remote/browser/remoteIndicator.ts | 20 +--- .../contrib/remote/browser/tunnelView.ts | 10 +- .../terminal/browser/baseTerminalBackend.ts | 5 +- .../browser/workspace.contribution.ts | 7 +- .../services/statusbar/browser/statusbar.ts | 16 +++- 16 files changed, 211 insertions(+), 92 deletions(-) diff --git a/build/lib/stylelint/vscode-known-variables.json b/build/lib/stylelint/vscode-known-variables.json index 6133fe142b4..73faa4aaa12 100644 --- a/build/lib/stylelint/vscode-known-variables.json +++ b/build/lib/stylelint/vscode-known-variables.json @@ -545,12 +545,16 @@ "--vscode-statusBar-noFolderBackground", "--vscode-statusBar-noFolderBorder", "--vscode-statusBar-noFolderForeground", - "--vscode-statusBar-offlineBackground", - "--vscode-statusBar-offlineForeground", + "--vscode-statusBarItem-offlineBackground", + "--vscode-statusBarItem-offlineForeground", + "--vscode-statusBarItem-offlineHoverBackground", + "--vscode-statusBarItem-offlineHoverForeground", "--vscode-statusBarItem-activeBackground", "--vscode-statusBarItem-compactHoverBackground", "--vscode-statusBarItem-errorBackground", "--vscode-statusBarItem-errorForeground", + "--vscode-statusBarItem-errorHoverBackground", + "--vscode-statusBarItem-errorHoverForeground", "--vscode-statusBarItem-focusBorder", "--vscode-statusBarItem-hoverBackground", "--vscode-statusBarItem-hoverForeground", @@ -560,8 +564,12 @@ "--vscode-statusBarItem-prominentHoverForeground", "--vscode-statusBarItem-remoteBackground", "--vscode-statusBarItem-remoteForeground", + "--vscode-statusBarItem-remoteHoverBackground", + "--vscode-statusBarItem-remoteHoverForeground", "--vscode-statusBarItem-warningBackground", "--vscode-statusBarItem-warningForeground", + "--vscode-statusBarItem-warningHoverBackground", + "--vscode-statusBarItem-warningHoverForeground", "--vscode-symbolIcon-arrayForeground", "--vscode-symbolIcon-booleanForeground", "--vscode-symbolIcon-classForeground", @@ -770,4 +778,4 @@ "--z-index-notebook-sticky-scroll", "--zoom-factor" ] -} \ No newline at end of file +} diff --git a/src/vs/workbench/api/browser/mainThreadStatusBar.ts b/src/vs/workbench/api/browser/mainThreadStatusBar.ts index 4e561ae88bb..00eb17f4982 100644 --- a/src/vs/workbench/api/browser/mainThreadStatusBar.ts +++ b/src/vs/workbench/api/browser/mainThreadStatusBar.ts @@ -56,7 +56,7 @@ export class MainThreadStatusBar implements MainThreadStatusBarShape { this._store.dispose(); } - $setEntry(entryId: string, id: string, extensionId: string | undefined, name: string, text: string, tooltip: IMarkdownString | string | undefined, command: Command | undefined, color: string | ThemeColor | undefined, backgroundColor: string | ThemeColor | undefined, alignLeft: boolean, priority: number | undefined, accessibilityInformation: IAccessibilityInformation | undefined): void { + $setEntry(entryId: string, id: string, extensionId: string | undefined, name: string, text: string, tooltip: IMarkdownString | string | undefined, command: Command | undefined, color: string | ThemeColor | undefined, backgroundColor: ThemeColor | undefined, alignLeft: boolean, priority: number | undefined, accessibilityInformation: IAccessibilityInformation | undefined): void { const kind = this.statusbarService.setOrUpdateEntry(entryId, id, extensionId, name, text, tooltip, command, color, backgroundColor, alignLeft, priority, accessibilityInformation); if (kind === StatusBarUpdateKind.DidDefine) { this._store.add(toDisposable(() => this.statusbarService.unsetEntry(entryId))); diff --git a/src/vs/workbench/api/browser/statusBarExtensionPoint.ts b/src/vs/workbench/api/browser/statusBarExtensionPoint.ts index cd2e439f8f6..99dd3279fe8 100644 --- a/src/vs/workbench/api/browser/statusBarExtensionPoint.ts +++ b/src/vs/workbench/api/browser/statusBarExtensionPoint.ts @@ -9,7 +9,7 @@ import { localize } from 'vs/nls'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { isProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions'; import { ExtensionsRegistry } from 'vs/workbench/services/extensions/common/extensionsRegistry'; -import { IStatusbarService, StatusbarAlignment as MainThreadStatusBarAlignment, IStatusbarEntryAccessor, IStatusbarEntry, StatusbarAlignment, IStatusbarEntryPriority } from 'vs/workbench/services/statusbar/browser/statusbar'; +import { IStatusbarService, StatusbarAlignment as MainThreadStatusBarAlignment, IStatusbarEntryAccessor, IStatusbarEntry, StatusbarAlignment, IStatusbarEntryPriority, StatusbarEntryKind } from 'vs/workbench/services/statusbar/browser/statusbar'; import { ThemeColor } from 'vs/base/common/themables'; import { Command } from 'vs/editor/common/languages'; import { IAccessibilityInformation, isAccessibilityInformation } from 'vs/platform/accessibility/common/accessibility'; @@ -21,6 +21,7 @@ import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/ import { Iterable } from 'vs/base/common/iterator'; import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; import { asStatusBarItemIdentifier } from 'vs/workbench/api/common/extHostTypes'; +import { STATUS_BAR_ERROR_ITEM_BACKGROUND, STATUS_BAR_WARNING_ITEM_BACKGROUND } from 'vs/workbench/common/theme'; // --- service @@ -48,7 +49,7 @@ export interface IExtensionStatusBarItemService { onDidChange: Event; - setOrUpdateEntry(id: string, statusId: string, extensionId: string | undefined, name: string, text: string, tooltip: IMarkdownString | string | undefined, command: Command | undefined, color: string | ThemeColor | undefined, backgroundColor: string | ThemeColor | undefined, alignLeft: boolean, priority: number | undefined, accessibilityInformation: IAccessibilityInformation | undefined): StatusBarUpdateKind; + setOrUpdateEntry(id: string, statusId: string, extensionId: string | undefined, name: string, text: string, tooltip: IMarkdownString | string | undefined, command: Command | undefined, color: string | ThemeColor | undefined, backgroundColor: ThemeColor | undefined, alignLeft: boolean, priority: number | undefined, accessibilityInformation: IAccessibilityInformation | undefined): StatusBarUpdateKind; unsetEntry(id: string): void; @@ -75,7 +76,7 @@ class ExtensionStatusBarItemService implements IExtensionStatusBarItemService { setOrUpdateEntry(entryId: string, id: string, extensionId: string | undefined, name: string, text: string, tooltip: IMarkdownString | string | undefined, - command: Command | undefined, color: string | ThemeColor | undefined, backgroundColor: string | ThemeColor | undefined, + command: Command | undefined, color: string | ThemeColor | undefined, backgroundColor: ThemeColor | undefined, alignLeft: boolean, priority: number | undefined, accessibilityInformation: IAccessibilityInformation | undefined ): StatusBarUpdateKind { // if there are icons in the text use the tooltip for the aria label @@ -91,7 +92,16 @@ class ExtensionStatusBarItemService implements IExtensionStatusBarItemService { ariaLabel += `, ${tooltipString}`; } } - const entry: IStatusbarEntry = { name, text, tooltip, command, color, backgroundColor, ariaLabel, role }; + let kind: StatusbarEntryKind | undefined = undefined; + switch (backgroundColor?.id) { + case STATUS_BAR_ERROR_ITEM_BACKGROUND: + case STATUS_BAR_WARNING_ITEM_BACKGROUND: + // override well known colors that map to status entry kinds to support associated themable hover colors + kind = backgroundColor.id === STATUS_BAR_ERROR_ITEM_BACKGROUND ? 'error' : 'warning'; + color = undefined; + backgroundColor = undefined; + } + const entry: IStatusbarEntry = { name, text, tooltip, command, color, backgroundColor, ariaLabel, role, kind }; if (typeof priority === 'undefined') { priority = 0; diff --git a/src/vs/workbench/browser/parts/editor/accessibilityStatus.ts b/src/vs/workbench/browser/parts/editor/accessibilityStatus.ts index de65eca21f0..5160d1e2791 100644 --- a/src/vs/workbench/browser/parts/editor/accessibilityStatus.ts +++ b/src/vs/workbench/browser/parts/editor/accessibilityStatus.ts @@ -13,8 +13,6 @@ import { ConfigurationTarget, IConfigurationService } from 'vs/platform/configur import { INotificationHandle, INotificationService, NotificationPriority } from 'vs/platform/notification/common/notification'; import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; import { IStatusbarEntryAccessor, IStatusbarService, StatusbarAlignment } from 'vs/workbench/services/statusbar/browser/statusbar'; -import { themeColorFromId } from 'vs/platform/theme/common/themeService'; -import { STATUS_BAR_PROMINENT_ITEM_BACKGROUND, STATUS_BAR_PROMINENT_ITEM_FOREGROUND } from 'vs/workbench/common/theme'; export class AccessibilityStatus extends Disposable implements IWorkbenchContribution { private screenReaderNotification: INotificationHandle | null = null; @@ -71,8 +69,7 @@ export class AccessibilityStatus extends Disposable implements IWorkbenchContrib text, ariaLabel: text, command: 'showEditorScreenReaderNotification', - backgroundColor: themeColorFromId(STATUS_BAR_PROMINENT_ITEM_BACKGROUND), - color: themeColorFromId(STATUS_BAR_PROMINENT_ITEM_FOREGROUND) + kind: 'prominent' }, 'status.editor.screenReaderMode', StatusbarAlignment.RIGHT, 100.6); } } else { diff --git a/src/vs/workbench/browser/parts/editor/editorStatus.ts b/src/vs/workbench/browser/parts/editor/editorStatus.ts index d18e4fc12f7..dcb7c46f57a 100644 --- a/src/vs/workbench/browser/parts/editor/editorStatus.ts +++ b/src/vs/workbench/browser/parts/editor/editorStatus.ts @@ -47,8 +47,6 @@ import { Event } from 'vs/base/common/event'; import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; import { IStatusbarEntryAccessor, IStatusbarService, StatusbarAlignment, IStatusbarEntry } from 'vs/workbench/services/statusbar/browser/statusbar'; import { IMarker, IMarkerService, MarkerSeverity, IMarkerData } from 'vs/platform/markers/common/markers'; -import { STATUS_BAR_PROMINENT_ITEM_BACKGROUND, STATUS_BAR_PROMINENT_ITEM_FOREGROUND } from 'vs/workbench/common/theme'; -import { themeColorFromId } from 'vs/platform/theme/common/themeService'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditorInput'; import { AutomaticLanguageDetectionLikelyWrongClassification, AutomaticLanguageDetectionLikelyWrongId, IAutomaticLanguageDetectionLikelyWrongData, ILanguageDetectionService } from 'vs/workbench/services/languageDetection/common/languageDetectionWorkerService'; @@ -381,8 +379,7 @@ export class EditorStatus extends Disposable implements IWorkbenchContribution { ariaLabel: text, tooltip: localize('disableTabMode', "Disable Accessibility Mode"), command: 'editor.action.toggleTabFocusMode', - backgroundColor: themeColorFromId(STATUS_BAR_PROMINENT_ITEM_BACKGROUND), - color: themeColorFromId(STATUS_BAR_PROMINENT_ITEM_FOREGROUND) + kind: 'prominent' }, 'status.editor.tabFocusMode', StatusbarAlignment.RIGHT, 100.7); } } else { @@ -400,8 +397,7 @@ export class EditorStatus extends Disposable implements IWorkbenchContribution { ariaLabel: text, tooltip: localize('disableColumnSelectionMode', "Disable Column Selection Mode"), command: 'editor.action.toggleColumnSelection', - backgroundColor: themeColorFromId(STATUS_BAR_PROMINENT_ITEM_BACKGROUND), - color: themeColorFromId(STATUS_BAR_PROMINENT_ITEM_FOREGROUND) + kind: 'prominent' }, 'status.editor.columnSelectionMode', StatusbarAlignment.RIGHT, 100.8); } } else { diff --git a/src/vs/workbench/browser/parts/statusbar/media/statusbarpart.css b/src/vs/workbench/browser/parts/statusbar/media/statusbarpart.css index 52662d0cb2e..d6897bf02d7 100644 --- a/src/vs/workbench/browser/parts/statusbar/media/statusbarpart.css +++ b/src/vs/workbench/browser/parts/statusbar/media/statusbarpart.css @@ -155,15 +155,6 @@ color: inherit; } -.monaco-workbench .part.statusbar > .items-container > .statusbar-item .status-bar-info { - color: var(--vscode-statusBarItem-prominentForeground); - background-color: var(--vscode-statusBarItem-prominentBackground); -} - -.monaco-workbench .part.statusbar > .items-container > .statusbar-item a.status-bar-info:hover:not(.disabled) { - background-color: var(--vscode-statusBarItem-prominentHoverBackground); -} - .monaco-workbench .part.statusbar > .items-container > .statusbar-item a:active:not(.disabled) { outline: 1px solid var(--vscode-contrastActiveBorder) !important; outline-offset: -1px; @@ -181,3 +172,55 @@ .monaco-workbench:not(.hc-light):not(.hc-black) .part.statusbar > .items-container > .statusbar-item a:hover:not(.disabled) { background-color: var(--vscode-statusBarItem-hoverBackground); } + +/** Status bar entry item kinds */ + +.monaco-workbench .part.statusbar > .items-container > .statusbar-item.warning-kind { + color: var(--vscode-statusBarItem-warningForeground); + background-color: var(--vscode-statusBarItem-warningBackground); +} + +.monaco-workbench .part.statusbar > .items-container > .statusbar-item.warning-kind a:hover:not(.disabled) { + color: var(--vscode-statusBarItem-warningHoverForeground); + background-color: var(--vscode-statusBarItem-warningHoverBackground) !important; +} + +.monaco-workbench .part.statusbar > .items-container > .statusbar-item.error-kind { + color: var(--vscode-statusBarItem-errorForeground); + background-color: var(--vscode-statusBarItem-errorBackground); +} + +.monaco-workbench .part.statusbar > .items-container > .statusbar-item.error-kind a:hover:not(.disabled) { + color: var(--vscode-statusBarItem-errorHoverForeground); + background-color: var(--vscode-statusBarItem-errorHoverBackground) !important; +} + +.monaco-workbench .part.statusbar > .items-container > .statusbar-item.prominent-kind { + color: var(--vscode-statusBarItem-prominentForeground); + background-color: var(--vscode-statusBarItem-prominentBackground); +} + +.monaco-workbench .part.statusbar > .items-container > .statusbar-item.prominent-kind a:hover:not(.disabled) { + color: var(--vscode-statusBarItem-prominentHoverForeground); + background-color: var(--vscode-statusBarItem-prominentHoverBackground) !important; +} + +.monaco-workbench .part.statusbar > .items-container > .statusbar-item.remote-kind { + color: var(--vscode-statusBarItem-remoteForeground); + background-color: var(--vscode-statusBarItem-remoteBackground); +} + +.monaco-workbench .part.statusbar > .items-container > .statusbar-item.remote-kind a:hover:not(.disabled) { + color: var(--vscode-statusBarItem-remoteHoverForeground); + background-color: var(--vscode-statusBarItem-remoteHoverBackground) !important; +} + +.monaco-workbench .part.statusbar > .items-container > .statusbar-item.offline-kind { + color: var(--vscode-statusBarItem-offlineForeground); + background-color: var(--vscode-statusBarItem-offlineBackground); +} + +.monaco-workbench .part.statusbar > .items-container > .statusbar-item.offline-kind a:hover:not(.disabled) { + color: var(--vscode-statusBarItem-offlineHoverForeground); + background-color: var(--vscode-statusBarItem-offlineHoverBackground) !important; +} diff --git a/src/vs/workbench/browser/parts/statusbar/statusbarItem.ts b/src/vs/workbench/browser/parts/statusbar/statusbarItem.ts index b1988505d95..39fd753e3d6 100644 --- a/src/vs/workbench/browser/parts/statusbar/statusbarItem.ts +++ b/src/vs/workbench/browser/parts/statusbar/statusbarItem.ts @@ -8,7 +8,7 @@ import { Disposable, MutableDisposable } from 'vs/base/common/lifecycle'; import { SimpleIconLabel } from 'vs/base/browser/ui/iconLabel/simpleIconLabel'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import { IStatusbarEntry, ShowTooltipCommand } from 'vs/workbench/services/statusbar/browser/statusbar'; +import { IStatusbarEntry, ShowTooltipCommand, StatusbarEntryKinds } from 'vs/workbench/services/statusbar/browser/statusbar'; import { WorkbenchActionExecutedEvent, WorkbenchActionExecutedClassification } from 'vs/base/common/actions'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { ThemeColor } from 'vs/base/common/themables'; @@ -156,6 +156,21 @@ export class StatusbarEntryItem extends Disposable { } } + const hasBackgroundColor = !!entry.backgroundColor || (entry.kind && entry.kind !== 'standard'); + + // Update: Kind + if (!this.entry || entry.kind !== this.entry.kind) { + for (const kind of StatusbarEntryKinds) { + this.container.classList.remove(`${kind}-kind`); + } + + if (entry.kind && entry.kind !== 'standard') { + this.container.classList.add(`${entry.kind}-kind`); + } + + this.container.classList.toggle('has-background-color', hasBackgroundColor); + } + // Update: Foreground if (!this.entry || entry.color !== this.entry.color) { this.applyColor(this.labelContainer, entry.color); @@ -163,7 +178,7 @@ export class StatusbarEntryItem extends Disposable { // Update: Background if (!this.entry || entry.backgroundColor !== this.entry.backgroundColor) { - this.container.classList.toggle('has-background-color', !!entry.backgroundColor); + this.container.classList.toggle('has-background-color', hasBackgroundColor); this.applyColor(this.container, entry.backgroundColor, true); } diff --git a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts index 1c949d44a00..a2938f04e10 100644 --- a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts +++ b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts @@ -20,7 +20,7 @@ import { EventHelper, createStyleSheet, addDisposableListener, EventType, clearN import { IStorageService } from 'vs/platform/storage/common/storage'; import { Parts, IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions'; -import { coalesce, equals } from 'vs/base/common/arrays'; +import { equals } from 'vs/base/common/arrays'; import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; import { ToggleStatusbarVisibilityAction } from 'vs/workbench/browser/actions/layoutActions'; import { assertIsDefined } from 'vs/base/common/types'; @@ -176,7 +176,7 @@ export class StatusbarPart extends Part implements IStatusbarService { private doAddEntry(entry: IStatusbarEntry, id: string, alignment: StatusbarAlignment, priority: IStatusbarEntryPriority): IStatusbarEntryAccessor { // View model item - const itemContainer = this.doCreateStatusItem(id, alignment, ...coalesce([entry.showBeak ? 'has-beak' : undefined])); + const itemContainer = this.doCreateStatusItem(id, alignment); const item = this.instantiationService.createInstance(StatusbarEntryItem, itemContainer, entry, this.hoverDelegate); // View model entry diff --git a/src/vs/workbench/common/theme.ts b/src/vs/workbench/common/theme.ts index bc3da309318..a4a46546750 100644 --- a/src/vs/workbench/common/theme.ts +++ b/src/vs/workbench/common/theme.ts @@ -515,28 +515,28 @@ export const STATUS_BAR_PROMINENT_ITEM_FOREGROUND = registerColor('statusBarItem light: STATUS_BAR_FOREGROUND, hcDark: STATUS_BAR_FOREGROUND, hcLight: STATUS_BAR_FOREGROUND -}, localize('statusBarProminentItemForeground', "Status bar prominent items foreground color. Prominent items stand out from other status bar entries to indicate importance. Change mode `Toggle Tab Key Moves Focus` from command palette to see an example. The status bar is shown in the bottom of the window.")); +}, localize('statusBarProminentItemForeground', "Status bar prominent items foreground color. Prominent items stand out from other status bar entries to indicate importance. The status bar is shown in the bottom of the window.")); export const STATUS_BAR_PROMINENT_ITEM_BACKGROUND = registerColor('statusBarItem.prominentBackground', { dark: Color.black.transparent(0.5), light: Color.black.transparent(0.5), hcDark: Color.black.transparent(0.5), hcLight: Color.black.transparent(0.5), -}, localize('statusBarProminentItemBackground', "Status bar prominent items background color. Prominent items stand out from other status bar entries to indicate importance. Change mode `Toggle Tab Key Moves Focus` from command palette to see an example. The status bar is shown in the bottom of the window.")); +}, localize('statusBarProminentItemBackground', "Status bar prominent items background color. Prominent items stand out from other status bar entries to indicate importance. The status bar is shown in the bottom of the window.")); + +export const STATUS_BAR_PROMINENT_ITEM_HOVER_FOREGROUND = registerColor('statusBarItem.prominentHoverForeground', { + dark: STATUS_BAR_ITEM_HOVER_FOREGROUND, + light: STATUS_BAR_ITEM_HOVER_FOREGROUND, + hcDark: STATUS_BAR_ITEM_HOVER_FOREGROUND, + hcLight: STATUS_BAR_ITEM_HOVER_FOREGROUND +}, localize('statusBarProminentItemHoverForeground', "Status bar prominent items foreground color when hovering. Prominent items stand out from other status bar entries to indicate importance. The status bar is shown in the bottom of the window.")); export const STATUS_BAR_PROMINENT_ITEM_HOVER_BACKGROUND = registerColor('statusBarItem.prominentHoverBackground', { dark: Color.black.transparent(0.3), light: Color.black.transparent(0.3), hcDark: Color.black.transparent(0.3), hcLight: null -}, localize('statusBarProminentItemHoverBackground', "Status bar prominent items background color when hovering. Prominent items stand out from other status bar entries to indicate importance. Change mode `Toggle Tab Key Moves Focus` from command palette to see an example. The status bar is shown in the bottom of the window.")); - -export const STATUS_BAR_PROMINENT_ITEM_HOVER_FOREGROUND = registerColor('statusBarItem.prominentHoverForeground', { - dark: STATUS_BAR_FOREGROUND, - light: STATUS_BAR_FOREGROUND, - hcDark: STATUS_BAR_FOREGROUND, - hcLight: STATUS_BAR_FOREGROUND -}, localize('statusBarProminentItemHoverForeground', "Status bar prominent items foreground color when hovering. Prominent items stand out from other status bar entries to indicate importance. Change mode `Toggle Tab Key Moves Focus` from command palette to see an example. The status bar is shown in the bottom of the window.")); +}, localize('statusBarProminentItemHoverBackground', "Status bar prominent items background color when hovering. Prominent items stand out from other status bar entries to indicate importance. The status bar is shown in the bottom of the window.")); export const STATUS_BAR_ERROR_ITEM_BACKGROUND = registerColor('statusBarItem.errorBackground', { dark: darken(errorForeground, .4), @@ -552,6 +552,20 @@ export const STATUS_BAR_ERROR_ITEM_FOREGROUND = registerColor('statusBarItem.err hcLight: Color.white }, localize('statusBarErrorItemForeground', "Status bar error items foreground color. Error items stand out from other status bar entries to indicate error conditions. The status bar is shown in the bottom of the window.")); +export const STATUS_BAR_ERROR_ITEM_HOVER_FOREGROUND = registerColor('statusBarItem.errorHoverForeground', { + dark: STATUS_BAR_ITEM_HOVER_FOREGROUND, + light: STATUS_BAR_ITEM_HOVER_FOREGROUND, + hcDark: STATUS_BAR_ITEM_HOVER_FOREGROUND, + hcLight: STATUS_BAR_ITEM_HOVER_FOREGROUND +}, localize('statusBarErrorItemHoverForeground', "Status bar error items foreground color when hovering. Error items stand out from other status bar entries to indicate error conditions. The status bar is shown in the bottom of the window.")); + +export const STATUS_BAR_ERROR_ITEM_HOVER_BACKGROUND = registerColor('statusBarItem.errorHoverBackground', { + dark: STATUS_BAR_ITEM_HOVER_BACKGROUND, + light: STATUS_BAR_ITEM_HOVER_BACKGROUND, + hcDark: STATUS_BAR_ITEM_HOVER_BACKGROUND, + hcLight: STATUS_BAR_ITEM_HOVER_BACKGROUND +}, localize('statusBarErrorItemHoverBackground', "Status bar error items background color when hovering. Error items stand out from other status bar entries to indicate error conditions. The status bar is shown in the bottom of the window.")); + export const STATUS_BAR_WARNING_ITEM_BACKGROUND = registerColor('statusBarItem.warningBackground', { dark: darken(editorWarningForeground, .4), light: darken(editorWarningForeground, .4), @@ -566,6 +580,20 @@ export const STATUS_BAR_WARNING_ITEM_FOREGROUND = registerColor('statusBarItem.w hcLight: Color.white }, localize('statusBarWarningItemForeground', "Status bar warning items foreground color. Warning items stand out from other status bar entries to indicate warning conditions. The status bar is shown in the bottom of the window.")); +export const STATUS_BAR_WARNING_ITEM_HOVER_FOREGROUND = registerColor('statusBarItem.warningHoverForeground', { + dark: STATUS_BAR_ITEM_HOVER_FOREGROUND, + light: STATUS_BAR_ITEM_HOVER_FOREGROUND, + hcDark: STATUS_BAR_ITEM_HOVER_FOREGROUND, + hcLight: STATUS_BAR_ITEM_HOVER_FOREGROUND +}, localize('statusBarWarningItemHoverForeground', "Status bar warning items foreground color when hovering. Warning items stand out from other status bar entries to indicate warning conditions. The status bar is shown in the bottom of the window.")); + +export const STATUS_BAR_WARNING_ITEM_HOVER_BACKGROUND = registerColor('statusBarItem.warningHoverBackground', { + dark: STATUS_BAR_ITEM_HOVER_BACKGROUND, + light: STATUS_BAR_ITEM_HOVER_BACKGROUND, + hcDark: STATUS_BAR_ITEM_HOVER_BACKGROUND, + hcLight: STATUS_BAR_ITEM_HOVER_BACKGROUND +}, localize('statusBarWarningItemHoverBackground', "Status bar warning items background color when hovering. Warning items stand out from other status bar entries to indicate warning conditions. The status bar is shown in the bottom of the window.")); + // < --- Activity Bar --- > @@ -657,20 +685,62 @@ export const PROFILE_BADGE_FOREGROUND = registerColor('profileBadge.foreground', // < --- Remote --- > -export const STATUS_BAR_HOST_NAME_BACKGROUND = registerColor('statusBarItem.remoteBackground', { +export const STATUS_BAR_REMOTE_ITEM_BACKGROUND = registerColor('statusBarItem.remoteBackground', { dark: ACTIVITY_BAR_BADGE_BACKGROUND, light: ACTIVITY_BAR_BADGE_BACKGROUND, hcDark: ACTIVITY_BAR_BADGE_BACKGROUND, hcLight: ACTIVITY_BAR_BADGE_BACKGROUND }, localize('statusBarItemHostBackground', "Background color for the remote indicator on the status bar.")); -export const STATUS_BAR_HOST_NAME_FOREGROUND = registerColor('statusBarItem.remoteForeground', { +export const STATUS_BAR_REMOTE_ITEM_FOREGROUND = registerColor('statusBarItem.remoteForeground', { dark: ACTIVITY_BAR_BADGE_FOREGROUND, light: ACTIVITY_BAR_BADGE_FOREGROUND, hcDark: ACTIVITY_BAR_BADGE_FOREGROUND, hcLight: ACTIVITY_BAR_BADGE_FOREGROUND }, localize('statusBarItemHostForeground', "Foreground color for the remote indicator on the status bar.")); +export const STATUS_BAR_REMOTE_ITEM_HOVER_FOREGROUND = registerColor('statusBarItem.remoteHoverForeground', { + dark: STATUS_BAR_ITEM_HOVER_FOREGROUND, + light: STATUS_BAR_ITEM_HOVER_FOREGROUND, + hcDark: STATUS_BAR_ITEM_HOVER_FOREGROUND, + hcLight: STATUS_BAR_ITEM_HOVER_FOREGROUND +}, localize('statusBarRemoteItemHoverForeground', "Foreground color for the remote indicator on the status bar when hovering.")); + +export const STATUS_BAR_REMOTE_ITEM_HOVER_BACKGROUND = registerColor('statusBarItem.remoteHoverBackground', { + dark: STATUS_BAR_ITEM_HOVER_BACKGROUND, + light: STATUS_BAR_ITEM_HOVER_BACKGROUND, + hcDark: STATUS_BAR_ITEM_HOVER_BACKGROUND, + hcLight: null +}, localize('statusBarRemoteItemHoverBackground', "Background color for the remote indicator on the status bar when hovering.")); + +export const STATUS_BAR_OFFLINE_ITEM_BACKGROUND = registerColor('statusBarItem.offlineBackground', { + dark: '#6c1717', + light: '#6c1717', + hcDark: '#6c1717', + hcLight: '#6c1717' +}, localize('statusBarItemOfflineBackground', "Status bar item background color when the workbench is offline.")); + +export const STATUS_BAR_OFFLINE_ITEM_FOREGROUND = registerColor('statusBarItem.offlineForeground', { + dark: STATUS_BAR_REMOTE_ITEM_FOREGROUND, + light: STATUS_BAR_REMOTE_ITEM_FOREGROUND, + hcDark: STATUS_BAR_REMOTE_ITEM_FOREGROUND, + hcLight: STATUS_BAR_REMOTE_ITEM_FOREGROUND +}, localize('statusBarItemOfflineForeground', "Status bar item foreground color when the workbench is offline.")); + +export const STATUS_BAR_OFFLINE_ITEM_HOVER_FOREGROUND = registerColor('statusBarItem.offlineHoverForeground', { + dark: STATUS_BAR_ITEM_HOVER_FOREGROUND, + light: STATUS_BAR_ITEM_HOVER_FOREGROUND, + hcDark: STATUS_BAR_ITEM_HOVER_FOREGROUND, + hcLight: STATUS_BAR_ITEM_HOVER_FOREGROUND +}, localize('statusBarOfflineItemHoverForeground', "Status bar item foreground hover color when the workbench is offline.")); + +export const STATUS_BAR_OFFLINE_ITEM_HOVER_BACKGROUND = registerColor('statusBarItem.offlineHoverBackground', { + dark: STATUS_BAR_ITEM_HOVER_BACKGROUND, + light: STATUS_BAR_ITEM_HOVER_BACKGROUND, + hcDark: STATUS_BAR_ITEM_HOVER_BACKGROUND, + hcLight: null +}, localize('statusBarOfflineItemHoverBackground', "Status bar item background hover color when the workbench is offline.")); + export const EXTENSION_BADGE_REMOTE_BACKGROUND = registerColor('extensionBadge.remoteBackground', { dark: ACTIVITY_BAR_BADGE_BACKGROUND, light: ACTIVITY_BAR_BADGE_BACKGROUND, diff --git a/src/vs/workbench/contrib/languageStatus/browser/languageStatus.contribution.ts b/src/vs/workbench/contrib/languageStatus/browser/languageStatus.contribution.ts index af697829ec1..3dd004897d2 100644 --- a/src/vs/workbench/contrib/languageStatus/browser/languageStatus.contribution.ts +++ b/src/vs/workbench/contrib/languageStatus/browser/languageStatus.contribution.ts @@ -11,14 +11,12 @@ import Severity from 'vs/base/common/severity'; import { getCodeEditor, ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { localize } from 'vs/nls'; import { Registry } from 'vs/platform/registry/common/platform'; -import { themeColorFromId } from 'vs/platform/theme/common/themeService'; -import { ThemeColor, ThemeIcon } from 'vs/base/common/themables'; +import { ThemeIcon } from 'vs/base/common/themables'; import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions, IWorkbenchContribution } from 'vs/workbench/common/contributions'; -import { STATUS_BAR_ERROR_ITEM_BACKGROUND, STATUS_BAR_ERROR_ITEM_FOREGROUND, STATUS_BAR_WARNING_ITEM_BACKGROUND, STATUS_BAR_WARNING_ITEM_FOREGROUND } from 'vs/workbench/common/theme'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { ILanguageStatus, ILanguageStatusService } from 'vs/workbench/services/languageStatus/common/languageStatusService'; import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle'; -import { IStatusbarEntry, IStatusbarEntryAccessor, IStatusbarService, ShowTooltipCommand, StatusbarAlignment } from 'vs/workbench/services/statusbar/browser/statusbar'; +import { IStatusbarEntry, IStatusbarEntryAccessor, IStatusbarService, ShowTooltipCommand, StatusbarAlignment, StatusbarEntryKind } from 'vs/workbench/services/statusbar/browser/statusbar'; import { parseLinkedText } from 'vs/base/common/linkedText'; import { Link } from 'vs/platform/opener/browser/link'; import { IOpenerService } from 'vs/platform/opener/common/opener'; @@ -367,14 +365,11 @@ class EditorStatusContribution implements IWorkbenchContribution { private static _asStatusbarEntry(item: ILanguageStatus): IStatusbarEntry { - let color: ThemeColor | undefined; - let backgroundColor: ThemeColor | undefined; + let kind: StatusbarEntryKind | undefined; if (item.severity === Severity.Warning) { - color = themeColorFromId(STATUS_BAR_WARNING_ITEM_FOREGROUND); - backgroundColor = themeColorFromId(STATUS_BAR_WARNING_ITEM_BACKGROUND); + kind = 'warning'; } else if (item.severity === Severity.Error) { - color = themeColorFromId(STATUS_BAR_ERROR_ITEM_FOREGROUND); - backgroundColor = themeColorFromId(STATUS_BAR_ERROR_ITEM_BACKGROUND); + kind = 'error'; } return { @@ -383,8 +378,7 @@ class EditorStatusContribution implements IWorkbenchContribution { ariaLabel: item.accessibilityInfo?.label ?? item.label, role: item.accessibilityInfo?.role, tooltip: item.command?.tooltip || new MarkdownString(item.detail, { isTrusted: true, supportThemeIcons: true }), - color, - backgroundColor, + kind, command: item.command }; } diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/editorStatusBar/editorStatusBar.ts b/src/vs/workbench/contrib/notebook/browser/contrib/editorStatusBar/editorStatusBar.ts index e7c3a8d12c2..633dedb4a4b 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/editorStatusBar/editorStatusBar.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/editorStatusBar/editorStatusBar.ts @@ -167,7 +167,7 @@ export class KernelStatus extends Disposable implements IWorkbenchContribution { text: nls.localize('kernel.select.label', "Select Kernel"), ariaLabel: nls.localize('kernel.select.label', "Select Kernel"), command: SELECT_KERNEL_ID, - backgroundColor: { id: 'statusBarItem.prominentBackground' } + kind: 'prominent' }, SELECT_KERNEL_ID, StatusbarAlignment.RIGHT, diff --git a/src/vs/workbench/contrib/remote/browser/remoteIndicator.ts b/src/vs/workbench/contrib/remote/browser/remoteIndicator.ts index 3130f1911ca..cab8b0d506e 100644 --- a/src/vs/workbench/contrib/remote/browser/remoteIndicator.ts +++ b/src/vs/workbench/contrib/remote/browser/remoteIndicator.ts @@ -4,8 +4,6 @@ *--------------------------------------------------------------------------------------------*/ import * as nls from 'vs/nls'; -import { STATUS_BAR_HOST_NAME_BACKGROUND, STATUS_BAR_HOST_NAME_FOREGROUND } from 'vs/workbench/common/theme'; -import { themeColorFromId } from 'vs/platform/theme/common/themeService'; import { IRemoteAgentService, remoteConnectionLatencyMeasurer } from 'vs/workbench/services/remote/common/remoteAgentService'; import { RunOnceScheduler, retry } from 'vs/base/common/async'; import { Emitter, Event } from 'vs/base/common/event'; @@ -45,7 +43,6 @@ import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegis import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; import { IProductService } from 'vs/platform/product/common/productService'; import { DomEmitter } from 'vs/base/browser/event'; -import { registerColor } from 'vs/platform/theme/common/colorRegistry'; import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; import { CancellationToken } from 'vs/base/common/cancellation'; import { ThemeIcon } from 'vs/base/common/themables'; @@ -53,20 +50,6 @@ import { infoIcon } from 'vs/workbench/contrib/extensions/browser/extensionsIcon import { IOpenerService } from 'vs/platform/opener/common/opener'; import { URI } from 'vs/base/common/uri'; -export const STATUS_BAR_OFFLINE_BACKGROUND = registerColor('statusBar.offlineBackground', { - dark: '#6c1717', - light: '#6c1717', - hcDark: '#6c1717', - hcLight: '#6c1717' -}, nls.localize('statusBarOfflineBackground', "Status bar background color when the workbench is offline. The status bar is shown in the bottom of the window")); - -export const STATUS_BAR_OFFLINE_FOREGROUND = registerColor('statusBar.offlineForeground', { - dark: STATUS_BAR_HOST_NAME_FOREGROUND, - light: STATUS_BAR_HOST_NAME_FOREGROUND, - hcDark: STATUS_BAR_HOST_NAME_FOREGROUND, - hcLight: STATUS_BAR_HOST_NAME_FOREGROUND -}, nls.localize('statusBarOfflineForeground', "Status bar foreground color when the workbench is offline. The status bar is shown in the bottom of the window")); - type ActionGroup = [string, Array]; interface RemoteExtensionMetadata { @@ -558,8 +541,7 @@ export class RemoteStatusIndicator extends Disposable implements IWorkbenchContr const properties: IStatusbarEntry = { name: nls.localize('remoteHost', "Remote Host"), - backgroundColor: themeColorFromId(this.networkState === 'offline' ? STATUS_BAR_OFFLINE_BACKGROUND : STATUS_BAR_HOST_NAME_BACKGROUND), - color: themeColorFromId(this.networkState === 'offline' ? STATUS_BAR_OFFLINE_FOREGROUND : STATUS_BAR_HOST_NAME_FOREGROUND), + kind: this.networkState === 'offline' ? 'offline' : 'remote', ariaLabel, text, showProgress, diff --git a/src/vs/workbench/contrib/remote/browser/tunnelView.ts b/src/vs/workbench/contrib/remote/browser/tunnelView.ts index 8f94225be44..ac01011049a 100644 --- a/src/vs/workbench/contrib/remote/browser/tunnelView.ts +++ b/src/vs/workbench/contrib/remote/browser/tunnelView.ts @@ -52,7 +52,7 @@ import { registerColor } from 'vs/platform/theme/common/colorRegistry'; import { IMarkdownString, MarkdownString } from 'vs/base/common/htmlContent'; import { IHoverDelegateOptions } from 'vs/base/browser/ui/iconLabel/iconHoverDelegate'; import { IHoverService } from 'vs/workbench/services/hover/browser/hover'; -import { STATUS_BAR_HOST_NAME_BACKGROUND } from 'vs/workbench/common/theme'; +import { STATUS_BAR_REMOTE_ITEM_BACKGROUND } from 'vs/workbench/common/theme'; import { Codicon } from 'vs/base/common/codicons'; import { defaultButtonStyles, defaultInputBoxStyles } from 'vs/platform/theme/browser/defaultStyles'; import { Attributes, CandidatePort, Tunnel, TunnelCloseReason, TunnelModel, TunnelSource, forwardedPortsViewEnabled, makeAddress, mapHasAddressLocalhostOrAllInterfaces, parseAddress } from 'vs/workbench/services/remote/common/tunnelModel'; @@ -1775,9 +1775,9 @@ MenuRegistry.appendMenuItem(MenuId.TunnelLocalAddressInline, ({ })); registerColor('ports.iconRunningProcessForeground', { - light: STATUS_BAR_HOST_NAME_BACKGROUND, - dark: STATUS_BAR_HOST_NAME_BACKGROUND, - hcDark: STATUS_BAR_HOST_NAME_BACKGROUND, - hcLight: STATUS_BAR_HOST_NAME_BACKGROUND + light: STATUS_BAR_REMOTE_ITEM_BACKGROUND, + dark: STATUS_BAR_REMOTE_ITEM_BACKGROUND, + hcDark: STATUS_BAR_REMOTE_ITEM_BACKGROUND, + hcLight: STATUS_BAR_REMOTE_ITEM_BACKGROUND }, nls.localize('portWithRunningProcess.foreground', "The color of the icon for a port that has an associated running process.")); diff --git a/src/vs/workbench/contrib/terminal/browser/baseTerminalBackend.ts b/src/vs/workbench/contrib/terminal/browser/baseTerminalBackend.ts index fcb01ae3e84..7710088cf64 100644 --- a/src/vs/workbench/contrib/terminal/browser/baseTerminalBackend.ts +++ b/src/vs/workbench/contrib/terminal/browser/baseTerminalBackend.ts @@ -8,9 +8,7 @@ import { Disposable } from 'vs/base/common/lifecycle'; import { Schemas } from 'vs/base/common/network'; import { localize } from 'vs/nls'; import { ICrossVersionSerializedTerminalState, IPtyHostController, ISerializedTerminalState, ITerminalLogService } from 'vs/platform/terminal/common/terminal'; -import { themeColorFromId } from 'vs/platform/theme/common/themeService'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; -import { STATUS_BAR_WARNING_ITEM_BACKGROUND, STATUS_BAR_WARNING_ITEM_FOREGROUND } from 'vs/workbench/common/theme'; import { TerminalCommandId } from 'vs/workbench/contrib/terminal/common/terminal'; import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver'; import { IHistoryService } from 'vs/workbench/services/history/common/history'; @@ -68,8 +66,7 @@ export abstract class BaseTerminalBackend extends Disposable { tooltip: localize('nonResponsivePtyHost', "The connection to the terminal's pty host process is unresponsive, terminals may stop working. Click to manually restart the pty host."), ariaLabel: localize('ptyHostStatus.ariaLabel', 'Pty Host is unresponsive'), command: TerminalCommandId.RestartPtyHost, - backgroundColor: themeColorFromId(STATUS_BAR_WARNING_ITEM_BACKGROUND), - color: themeColorFromId(STATUS_BAR_WARNING_ITEM_FOREGROUND), + kind: 'warning' }; } statusBarAccessor = statusBarService.addEntry(unresponsiveStatusBarEntry, 'ptyHostStatus', StatusbarAlignment.LEFT); diff --git a/src/vs/workbench/contrib/workspace/browser/workspace.contribution.ts b/src/vs/workbench/contrib/workspace/browser/workspace.contribution.ts index 6d705492fe9..8bc95f4f591 100644 --- a/src/vs/workbench/contrib/workspace/browser/workspace.contribution.ts +++ b/src/vs/workbench/contrib/workspace/browser/workspace.contribution.ts @@ -32,7 +32,6 @@ import { isEmptyWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier, isSingleF import { dirname, resolve } from 'vs/base/common/path'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IMarkdownString, MarkdownString } from 'vs/base/common/htmlContent'; -import { STATUS_BAR_PROMINENT_ITEM_BACKGROUND, STATUS_BAR_PROMINENT_ITEM_FOREGROUND } from 'vs/workbench/common/theme'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { IHostService } from 'vs/workbench/services/host/browser/host'; import { IBannerItem, IBannerService } from 'vs/workbench/services/banner/browser/bannerService'; @@ -527,9 +526,6 @@ export class WorkspaceTrustUXHandler extends Disposable implements IWorkbenchCon private getStatusbarEntry(trusted: boolean): IStatusbarEntry { const text = workspaceTrustToString(trusted); - const backgroundColor = { id: STATUS_BAR_PROMINENT_ITEM_BACKGROUND }; - const color = { id: STATUS_BAR_PROMINENT_ITEM_FOREGROUND }; - let ariaLabel = ''; let toolTip: IMarkdownString | string | undefined; switch (this.workspaceContextService.getWorkbenchState()) { @@ -586,8 +582,7 @@ export class WorkspaceTrustUXHandler extends Disposable implements IWorkbenchCon ariaLabel: ariaLabel, tooltip: toolTip, command: MANAGE_TRUST_COMMAND_ID, - backgroundColor, - color + kind: 'prominent' }; } diff --git a/src/vs/workbench/services/statusbar/browser/statusbar.ts b/src/vs/workbench/services/statusbar/browser/statusbar.ts index e38c45d1cf3..2e5abde6fba 100644 --- a/src/vs/workbench/services/statusbar/browser/statusbar.ts +++ b/src/vs/workbench/services/statusbar/browser/statusbar.ts @@ -153,6 +153,9 @@ export interface IStatusbarStyleOverride { readonly border?: ColorIdentifier; } +export type StatusbarEntryKind = 'standard' | 'warning' | 'error' | 'prominent' | 'remote' | 'offline'; +export const StatusbarEntryKinds: StatusbarEntryKind[] = ['standard', 'warning', 'error', 'prominent', 'remote', 'offline']; + /** * A declarative way of describing a status bar entry */ @@ -188,12 +191,16 @@ export interface IStatusbarEntry { readonly tooltip?: string | IMarkdownString | HTMLElement; /** - * An optional color to use for the entry + * An optional color to use for the entry. + * + * @deprecated Use `kind` instead to support themable hover styles. */ readonly color?: string | ThemeColor; /** - * An optional background color to use for the entry + * An optional background color to use for the entry. + * + * @deprecated Use `kind` instead to support themable hover styles. */ readonly backgroundColor?: string | ThemeColor; @@ -215,6 +222,11 @@ export interface IStatusbarEntry { * specified, `syncing` will be used. */ readonly showProgress?: boolean | 'syncing' | 'loading'; + + /** + * The kind of status bar entry. This applies different colors to the entry. + */ + readonly kind?: StatusbarEntryKind; } export interface IStatusbarEntryAccessor extends IDisposable { From 02c34a9476ed77ebb4198ea00464286f79a39f47 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Tue, 22 Aug 2023 03:43:50 -0700 Subject: [PATCH 069/221] Add explain quick fix kind This hasn't gone through the API process yet. We need some way of indicating the quick fix kind such that they can be presented in a different way. The main use case here is a sparkle icon for AI suggests but it could be expanded in the future Part of #162950 --- src/vs/platform/terminal/common/terminal.ts | 1 + .../terminal/browser/media/terminal.css | 5 ++ .../quickFix/browser/quickFix.ts | 1 + .../quickFix/browser/quickFixAddon.ts | 53 +++++++++++++------ .../browser/terminalQuickFixService.ts | 8 +++ 5 files changed, 51 insertions(+), 17 deletions(-) diff --git a/src/vs/platform/terminal/common/terminal.ts b/src/vs/platform/terminal/common/terminal.ts index 9dee3d5b41a..235d8efdbe8 100644 --- a/src/vs/platform/terminal/common/terminal.ts +++ b/src/vs/platform/terminal/common/terminal.ts @@ -966,6 +966,7 @@ export interface ITerminalCommandSelector { outputMatcher?: ITerminalOutputMatcher; exitStatus: boolean; commandExitResult: 'success' | 'error'; + kind?: 'fix' | 'explain'; } export interface ITerminalBackend { diff --git a/src/vs/workbench/contrib/terminal/browser/media/terminal.css b/src/vs/workbench/contrib/terminal/browser/media/terminal.css index 1b240eafdab..96e52e4816c 100644 --- a/src/vs/workbench/contrib/terminal/browser/media/terminal.css +++ b/src/vs/workbench/contrib/terminal/browser/media/terminal.css @@ -486,6 +486,11 @@ color: var(--vscode-editorLightBulb-foreground) !important; background-color: var(--vscode-terminal-background, --vscode-panel-background); } +.monaco-workbench .terminal .terminal-command-decoration.quick-fix.explainOnly { + /* Use success background to blend in with the terminal better as it's lower priority. We will + * probably want to add an explicit color for this eventually. */ + color: var(--vscode-terminalCommandDecoration-successBackground) !important; +} .terminal-scroll-highlight { left: 0; diff --git a/src/vs/workbench/contrib/terminalContrib/quickFix/browser/quickFix.ts b/src/vs/workbench/contrib/terminalContrib/quickFix/browser/quickFix.ts index 8a13380b971..f576102fe85 100644 --- a/src/vs/workbench/contrib/terminalContrib/quickFix/browser/quickFix.ts +++ b/src/vs/workbench/contrib/terminalContrib/quickFix/browser/quickFix.ts @@ -56,6 +56,7 @@ export interface ITerminalQuickFixOptions { commandLineMatcher: string | RegExp; outputMatcher?: ITerminalOutputMatcher; commandExitResult: 'success' | 'error'; + kind?: 'fix' | 'explain'; } export interface ITerminalQuickFix { diff --git a/src/vs/workbench/contrib/terminalContrib/quickFix/browser/quickFixAddon.ts b/src/vs/workbench/contrib/terminalContrib/quickFix/browser/quickFixAddon.ts index 0631a1e4e04..9f1ccc65e8c 100644 --- a/src/vs/workbench/contrib/terminalContrib/quickFix/browser/quickFixAddon.ts +++ b/src/vs/workbench/contrib/terminalContrib/quickFix/browser/quickFixAddon.ts @@ -36,9 +36,8 @@ import { Codicon } from 'vs/base/common/codicons'; import { ThemeIcon } from 'vs/base/common/themables'; import { ICommandService } from 'vs/platform/commands/common/commands'; -const quickFixSelectors = [ +const quickFixClasses = [ DecorationSelector.QuickFix, - DecorationSelector.LightBulb, DecorationSelector.Codicon, DecorationSelector.CommandDecoration, DecorationSelector.XtermDecoration @@ -116,7 +115,7 @@ export class TerminalQuickFixAddon extends Disposable implements ITerminalAddon, } // TODO: What's documentation do? Need a vscode command? - const actions = this._currentRenderContext.quickFixes.map(f => new TerminalQuickFixItem(f, f.type, f.source, f.label)); + const actions = this._currentRenderContext.quickFixes.map(f => new TerminalQuickFixItem(f, f.type, f.source, f.label, f.kind)); const documentation = this._currentRenderContext.quickFixes.map(f => { return { id: f.source, title: f.label, tooltip: f.source }; }); const actionSet = { // TODO: Documentation and actions are separate? @@ -150,7 +149,8 @@ export class TerminalQuickFixAddon extends Disposable implements ITerminalAddon, type: 'unresolved', commandLineMatcher: selector.commandLineMatcher, outputMatcher: selector.outputMatcher, - commandExitResult: selector.commandExitResult + commandExitResult: selector.commandExitResult, + kind: selector.kind }); this._registeredSelectors.add(selector.id); this._commandListeners.set(matcherKey, currentOptions); @@ -192,7 +192,14 @@ export class TerminalQuickFixAddon extends Disposable implements ITerminalAddon, } const id = selector.id; await this._extensionService.activateByEvent(`onTerminalQuickFixRequest:${id}`); - return this._quickFixService.providers.get(id)?.provideTerminalQuickFixes(command, lines, { type: 'resolved', commandLineMatcher: selector.commandLineMatcher, outputMatcher: selector.outputMatcher, commandExitResult: selector.commandExitResult, id: selector.id }, new CancellationTokenSource().token); + return this._quickFixService.providers.get(id)?.provideTerminalQuickFixes(command, lines, { + type: 'resolved', + commandLineMatcher: selector.commandLineMatcher, + outputMatcher: selector.outputMatcher, + commandExitResult: selector.commandExitResult, + kind: selector.kind, + id: selector.id + }, new CancellationTokenSource().token); }; const result = await getQuickFixesForCommand(aliases, terminal, command, this._commandListeners, this._commandService, this._openerService, this._labelService, this._onDidRequestRerunCommand, resolver); if (!result) { @@ -266,7 +273,13 @@ export class TerminalQuickFixAddon extends Disposable implements ITerminalAddon, return; } - e.classList.add(...quickFixSelectors); + e.classList.add(...quickFixClasses); + const isExplainOnly = fixes.every(e => e.kind === 'explain'); + if (isExplainOnly) { + e.classList.add('explainOnly'); + } + e.classList.add(...ThemeIcon.asClassNameArray(isExplainOnly ? Codicon.sparkle : Codicon.lightBulb)); + updateLayout(this._configurationService, e); this._audioCueService.playAudioCue(AudioCue.terminalQuickFix); @@ -285,6 +298,7 @@ export class TerminalQuickFixAddon extends Disposable implements ITerminalAddon, export interface ITerminalAction extends IAction { type: TerminalQuickFixType; + kind?: 'fix' | 'explain'; source: string; uri?: URI; command?: string; @@ -351,6 +365,7 @@ export async function getQuickFixesForCommand( const label = localize('quickFix.command', 'Run: {0}', fix.terminalCommand); action = { type: TerminalQuickFixType.TerminalCommand, + kind: option.kind, class: undefined, source: quickFix.source, id: quickFix.id, @@ -384,6 +399,7 @@ export async function getQuickFixesForCommand( id: quickFix.id, label, type: TerminalQuickFixType.Opener, + kind: option.kind, class: undefined, enabled: true, run: () => openerService.open(fix.uri), @@ -397,6 +413,7 @@ export async function getQuickFixesForCommand( action = { source: 'builtin', type: fix.type, + kind: option.kind, id: fix.id, label: fix.label, class: fix.class, @@ -413,6 +430,7 @@ export async function getQuickFixesForCommand( action = { source: quickFix.source, type: fix.type, + kind: option.kind, id: fix.id, label: fix.title, class: undefined, @@ -441,22 +459,20 @@ function convertToQuickFixOptions(selectorProvider: ITerminalQuickFixProviderSel commandLineMatcher: selectorProvider.selector.commandLineMatcher, outputMatcher: selectorProvider.selector.outputMatcher, commandExitResult: selectorProvider.selector.commandExitResult, + kind: selectorProvider.selector.kind, getQuickFixes: selectorProvider.provider.provideTerminalQuickFixes }; } class TerminalQuickFixItem { - action: ITerminalAction; - type: TerminalQuickFixType; - disabled?: boolean; - title?: string; - source: string; - constructor(action: ITerminalAction, type: TerminalQuickFixType, source: string, title?: string, disabled?: boolean) { - this.action = action; - this.disabled = disabled; - this.title = title; - this.source = source; - this.type = type; + readonly disabled = false; + constructor( + readonly action: ITerminalAction, + readonly type: TerminalQuickFixType, + readonly source: string, + readonly title: string | undefined, + readonly kind: 'fix' | 'explain' = 'fix' + ) { } } @@ -488,6 +504,9 @@ function toActionWidgetItems(inputQuickFixes: readonly TerminalQuickFixItem[], s } function getQuickFixIcon(quickFix: TerminalQuickFixItem): ThemeIcon { + if (quickFix.kind === 'explain') { + return Codicon.sparkle; + } switch (quickFix.type) { case TerminalQuickFixType.Opener: if ('uri' in quickFix.action && quickFix.action.uri) { diff --git a/src/vs/workbench/contrib/terminalContrib/quickFix/browser/terminalQuickFixService.ts b/src/vs/workbench/contrib/terminalContrib/quickFix/browser/terminalQuickFixService.ts index 4119c99c047..61b17085bb6 100644 --- a/src/vs/workbench/contrib/terminalContrib/quickFix/browser/terminalQuickFixService.ts +++ b/src/vs/workbench/contrib/terminalContrib/quickFix/browser/terminalQuickFixService.ts @@ -139,6 +139,14 @@ const quickFixExtensionPoint = ExtensionsRegistry.registerExtensionPoint Date: Tue, 22 Aug 2023 03:47:16 -0700 Subject: [PATCH 070/221] Fix var fallback --- src/vs/workbench/contrib/terminal/browser/media/terminal.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/terminal/browser/media/terminal.css b/src/vs/workbench/contrib/terminal/browser/media/terminal.css index 96e52e4816c..7bf0d8cd1c0 100644 --- a/src/vs/workbench/contrib/terminal/browser/media/terminal.css +++ b/src/vs/workbench/contrib/terminal/browser/media/terminal.css @@ -484,7 +484,7 @@ } .monaco-workbench .terminal .terminal-command-decoration.quick-fix { color: var(--vscode-editorLightBulb-foreground) !important; - background-color: var(--vscode-terminal-background, --vscode-panel-background); + background-color: var(--vscode-terminal-background, var(--vscode-panel-background)); } .monaco-workbench .terminal .terminal-command-decoration.quick-fix.explainOnly { /* Use success background to blend in with the terminal better as it's lower priority. We will From 5f97b6bf4fbdaf490152ecf88badb9f59f866e80 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Tue, 22 Aug 2023 03:55:36 -0700 Subject: [PATCH 071/221] Remove un used enum value --- .../contrib/terminal/browser/xterm/decorationStyles.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/browser/xterm/decorationStyles.ts b/src/vs/workbench/contrib/terminal/browser/xterm/decorationStyles.ts index 46ee2d10d7a..4d475759e0b 100644 --- a/src/vs/workbench/contrib/terminal/browser/xterm/decorationStyles.ts +++ b/src/vs/workbench/contrib/terminal/browser/xterm/decorationStyles.ts @@ -29,8 +29,7 @@ export const enum DecorationSelector { Codicon = 'codicon', XtermDecoration = 'xterm-decoration', OverviewRuler = '.xterm-decoration-overview-ruler', - QuickFix = 'quick-fix', - LightBulb = 'codicon-light-bulb' + QuickFix = 'quick-fix' } export class TerminalDecorationHoverManager extends Disposable { From b191ce214320cff5c1d89e0d4a511e04a958eb34 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Tue, 22 Aug 2023 03:57:54 -0700 Subject: [PATCH 072/221] Fix var fallback in terminal Fixes #190965 --- .../contrib/terminal/browser/media/terminal.css | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/browser/media/terminal.css b/src/vs/workbench/contrib/terminal/browser/media/terminal.css index 1b240eafdab..3e92460720e 100644 --- a/src/vs/workbench/contrib/terminal/browser/media/terminal.css +++ b/src/vs/workbench/contrib/terminal/browser/media/terminal.css @@ -20,7 +20,7 @@ visibility: hidden; } .monaco-workbench .part.panel .pane-body.integrated-terminal .terminal-outer-container { - background-color: var(--vscode-terminal-background, --vscode-panel-background); + background-color: var(--vscode-terminal-background, var(--vscode-panel-background)); } .monaco-workbench .pane-body.integrated-terminal .terminal-outer-container, .monaco-workbench .pane-body.integrated-terminal .terminal-groups-container, @@ -32,7 +32,7 @@ } .monaco-workbench .part.sidebar .pane-body.integrated-terminal .terminal-outer-container, .monaco-workbench .part.auxiliarybar .pane-body.integrated-terminal .terminal-outer-container { - background-color: var(--vscode-terminal-background, --vscode-sideBar-background); + background-color: var(--vscode-terminal-background, var(--vscode-sideBar-background)); } .monaco-workbench .pane-body.integrated-terminal .split-view-view:not(:first-child), @@ -41,7 +41,7 @@ } .monaco-workbench .pane-body.integrated-terminal .terminal-drop-overlay { - background-color: var(--vscode-terminal-dropBackground, --vscode-editorGroup-dropBackground); + background-color: var(--vscode-terminal-dropBackground, var(--vscode-editorGroup-dropBackground)); } .monaco-workbench .pane-body.integrated-terminal .terminal-tabs-entry.is-active::before { @@ -78,7 +78,7 @@ } .monaco-workbench .terminal-editor .terminal-wrapper { - background-color: var(--vscode-terminal-background, --vscode-editorPane-background); + background-color: var(--vscode-terminal-background, var(--vscode-editorPane-background)); } .monaco-workbench .terminal-editor .terminal-wrapper, .monaco-workbench .pane-body.integrated-terminal .terminal-wrapper { @@ -484,7 +484,7 @@ } .monaco-workbench .terminal .terminal-command-decoration.quick-fix { color: var(--vscode-editorLightBulb-foreground) !important; - background-color: var(--vscode-terminal-background, --vscode-panel-background); + background-color: var(--vscode-terminal-background, var(--vscode-panel-background)); } .terminal-scroll-highlight { @@ -583,7 +583,7 @@ pointer-events: all; opacity: 1; z-index: 33; - background-color: var(--vscode-terminal-background, --vscode-panel-background); + background-color: var(--vscode-terminal-background, var(--vscode-panel-background)); } .monaco-workbench .xterm.terminal.hide { From 515c6b204fefa52688c8ff92757ff69d0917a36f Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 22 Aug 2023 15:27:52 +0200 Subject: [PATCH 073/221] Unicode codepoint 0x202E causes the default filename in the tab title to also be right to left (fix #190133) (#190980) --- .../untitled/common/untitledTextEditorModel.ts | 3 ++- .../untitled/test/browser/untitledTextEditor.test.ts | 10 +++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/services/untitled/common/untitledTextEditorModel.ts b/src/vs/workbench/services/untitled/common/untitledTextEditorModel.ts index 93d906d886e..4b745f7af41 100644 --- a/src/vs/workbench/services/untitled/common/untitledTextEditorModel.ts +++ b/src/vs/workbench/services/untitled/common/untitledTextEditorModel.ts @@ -419,7 +419,8 @@ export class UntitledTextEditorModel extends BaseTextEditorModel implements IUnt startColumn: 1, endColumn: UntitledTextEditorModel.FIRST_LINE_NAME_CANDIDATE_MAX_LENGTH + 1 // first cap at FIRST_LINE_NAME_CANDIDATE_MAX_LENGTH }) - .trim().replace(/\s+/g, ' '); // normalize whitespaces + .trim().replace(/\s+/g, ' ') // normalize whitespaces + .replace(/\u202E/g, ''); // drop Right-to-Left Override character (#190133) firstLineText = firstLineText.substr(0, getCharContainingOffset( // finally cap at FIRST_LINE_NAME_MAX_LENGTH (grapheme aware #111235) firstLineText, UntitledTextEditorModel.FIRST_LINE_NAME_MAX_LENGTH)[0] diff --git a/src/vs/workbench/services/untitled/test/browser/untitledTextEditor.test.ts b/src/vs/workbench/services/untitled/test/browser/untitledTextEditor.test.ts index c724a93fd1b..935b78a3dfd 100644 --- a/src/vs/workbench/services/untitled/test/browser/untitledTextEditor.test.ts +++ b/src/vs/workbench/services/untitled/test/browser/untitledTextEditor.test.ts @@ -542,10 +542,14 @@ suite('Untitled text editors', () => { assert.strictEqual(input.getName(), '123456789012345678901234567890123456789'); assert.strictEqual(model.name, '123456789012345678901234567890123456789'); - assert.strictEqual(counter, 6); + model.textEditorModel?.setValue('hello\u202Eworld'); // do not allow RTL in names (#190133) + assert.strictEqual(input.getName(), 'helloworld'); + assert.strictEqual(model.name, 'helloworld'); + + assert.strictEqual(counter, 7); model.textEditorModel?.setValue('Hello\nWorld'); - assert.strictEqual(counter, 7); + assert.strictEqual(counter, 8); function createSingleEditOp(text: string, positionLineNumber: number, positionColumn: number, selectionLineNumber: number = positionLineNumber, selectionColumn: number = positionColumn): ISingleEditOperation { const range = new Range( @@ -563,7 +567,7 @@ suite('Untitled text editors', () => { } model.textEditorModel?.applyEdits([createSingleEditOp('hello', 2, 2)]); - assert.strictEqual(counter, 7); // change was not on first line + assert.strictEqual(counter, 8); // change was not on first line input.dispose(); model.dispose(); From 74c02f917d71d9efe3d7be7e3d8d32433affdefb Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Tue, 22 Aug 2023 15:40:28 +0200 Subject: [PATCH 074/221] changing the fallback of a variable to variable --- src/vs/editor/browser/viewParts/lines/viewLines.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/editor/browser/viewParts/lines/viewLines.css b/src/vs/editor/browser/viewParts/lines/viewLines.css index 8fff7ae3155..fe686d3e441 100644 --- a/src/vs/editor/browser/viewParts/lines/viewLines.css +++ b/src/vs/editor/browser/viewParts/lines/viewLines.css @@ -20,8 +20,8 @@ } .mtkoverflow { - background-color: var(--vscode-button-background, --vscode-editor-background); - color: var(--vscode-button-foreground, --vscode-editor-foreground); + background-color: var(--vscode-button-background, var(--vscode-editor-background)); + color: var(--vscode-button-foreground, var(--vscode-editor-foreground)); border-width: 1px; border-style: solid; border-color: var(--vscode-contrastBorder); From 2c9e2b85b2191c184f118e5fc99e093546e2cce1 Mon Sep 17 00:00:00 2001 From: Ulugbek Abdullaev Date: Tue, 22 Aug 2023 15:46:44 +0200 Subject: [PATCH 075/221] use `LanguageFeaturesService` to support `MappedEditsProvider`s instead of creating a new `MappedEditsService` --- src/vs/editor/common/languages.ts | 32 ++++++++- .../common/services/languageFeatures.ts | 4 +- .../services/languageFeaturesService.ts | 3 +- src/vs/monaco.d.ts | 24 +++++++ .../api/browser/extensionHost.contribution.ts | 1 - .../api/browser/mainThreadLanguageFeatures.ts | 21 ++++++ .../api/browser/mainThreadMappedEdits.ts | 57 ---------------- .../workbench/api/common/extHost.api.impl.ts | 4 +- .../workbench/api/common/extHost.protocol.ts | 15 +---- .../api/common/extHostLanguageFeatures.ts | 52 ++++++++++++++- .../api/common/extHostMappedEdits.ts | 61 ----------------- .../api/common/extHostTypeConverters.ts | 7 +- .../browser/actions/chatCodeblockActions.ts | 33 +++++++--- .../common/mappedEdits.contribution.ts | 44 ++++++++++--- .../mappedEdits/browser/mappedEditsService.ts | 51 --------------- .../mappedEdits/common/mappedEdits.ts | 65 ------------------- src/vs/workbench/workbench.common.main.ts | 1 - 17 files changed, 196 insertions(+), 279 deletions(-) delete mode 100644 src/vs/workbench/api/browser/mainThreadMappedEdits.ts delete mode 100644 src/vs/workbench/api/common/extHostMappedEdits.ts delete mode 100644 src/vs/workbench/services/mappedEdits/browser/mappedEditsService.ts delete mode 100644 src/vs/workbench/services/mappedEdits/common/mappedEdits.ts diff --git a/src/vs/editor/common/languages.ts b/src/vs/editor/common/languages.ts index 409b993d05b..15b63cf0386 100644 --- a/src/vs/editor/common/languages.ts +++ b/src/vs/editor/common/languages.ts @@ -16,7 +16,7 @@ import { URI, UriComponents } from 'vs/base/common/uri'; import { EditOperation, ISingleEditOperation } from 'vs/editor/common/core/editOperation'; import { IPosition, Position } from 'vs/editor/common/core/position'; import { IRange, Range } from 'vs/editor/common/core/range'; -import { Selection } from 'vs/editor/common/core/selection'; +import { ISelection, Selection } from 'vs/editor/common/core/selection'; import { LanguageId } from 'vs/editor/common/encodedTokenAttributes'; import * as model from 'vs/editor/common/model'; import { TokenizationRegistry as TokenizationRegistryImpl } from 'vs/editor/common/tokenizationRegistry'; @@ -2033,3 +2033,33 @@ export interface DocumentOnDropEditProvider { provideDocumentOnDropEdits(model: model.ITextModel, position: IPosition, dataTransfer: IReadonlyVSDataTransfer, token: CancellationToken): ProviderResult; } + +export interface RelatedContextItem { + readonly uri: URI; + readonly range: IRange; +} + +export interface MappedEditsContext { + selections: ISelection[]; + related: RelatedContextItem[]; +} + +export interface MappedEditsProvider { + + /** + * Provider maps code blocks from the chat into a workspace edit. + * + * @param document The document to provide mapped edits for. + * @param codeBlocks Code blocks that come from an LLM's reply. + * "Insert at cursor" in the panel chat only sends one edit that the user clicks on, but inline chat can send multiple blocks and let the lang server decide what to do with them. + * @param context The context for providing mapped edits. + * @param token A cancellation token. + * @returns A provider result of text edits. + */ + provideMappedEdits( + document: model.ITextModel, + codeBlocks: string[], + context: MappedEditsContext, + token: CancellationToken + ): Promise; +} diff --git a/src/vs/editor/common/services/languageFeatures.ts b/src/vs/editor/common/services/languageFeatures.ts index 2c80887df1a..df53beaecdb 100644 --- a/src/vs/editor/common/services/languageFeatures.ts +++ b/src/vs/editor/common/services/languageFeatures.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { LanguageFeatureRegistry, NotebookInfoResolver } from 'vs/editor/common/languageFeatureRegistry'; -import { CodeActionProvider, CodeLensProvider, CompletionItemProvider, DeclarationProvider, DefinitionProvider, DocumentColorProvider, DocumentFormattingEditProvider, DocumentHighlightProvider, DocumentOnDropEditProvider, DocumentPasteEditProvider, DocumentRangeFormattingEditProvider, DocumentRangeSemanticTokensProvider, DocumentSemanticTokensProvider, DocumentSymbolProvider, EvaluatableExpressionProvider, FoldingRangeProvider, HoverProvider, ImplementationProvider, InlayHintsProvider, InlineCompletionsProvider, InlineValuesProvider, LinkedEditingRangeProvider, LinkProvider, OnTypeFormattingEditProvider, ReferenceProvider, RenameProvider, SelectionRangeProvider, SignatureHelpProvider, TypeDefinitionProvider } from 'vs/editor/common/languages'; +import { CodeActionProvider, CodeLensProvider, CompletionItemProvider, DeclarationProvider, DefinitionProvider, DocumentColorProvider, DocumentFormattingEditProvider, DocumentHighlightProvider, DocumentOnDropEditProvider, DocumentPasteEditProvider, DocumentRangeFormattingEditProvider, DocumentRangeSemanticTokensProvider, DocumentSemanticTokensProvider, DocumentSymbolProvider, EvaluatableExpressionProvider, FoldingRangeProvider, HoverProvider, ImplementationProvider, InlayHintsProvider, InlineCompletionsProvider, InlineValuesProvider, LinkedEditingRangeProvider, LinkProvider, MappedEditsProvider, OnTypeFormattingEditProvider, ReferenceProvider, RenameProvider, SelectionRangeProvider, SignatureHelpProvider, TypeDefinitionProvider } from 'vs/editor/common/languages'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; export const ILanguageFeaturesService = createDecorator('ILanguageFeaturesService'); @@ -71,6 +71,8 @@ export interface ILanguageFeaturesService { readonly documentOnDropEditProvider: LanguageFeatureRegistry; + readonly mappedEditsProvider: LanguageFeatureRegistry; + // -- setNotebookTypeResolver(resolver: NotebookInfoResolver | undefined): void; diff --git a/src/vs/editor/common/services/languageFeaturesService.ts b/src/vs/editor/common/services/languageFeaturesService.ts index 35d321b4ef2..3ef13891fb7 100644 --- a/src/vs/editor/common/services/languageFeaturesService.ts +++ b/src/vs/editor/common/services/languageFeaturesService.ts @@ -5,7 +5,7 @@ import { URI } from 'vs/base/common/uri'; import { LanguageFeatureRegistry, NotebookInfo, NotebookInfoResolver } from 'vs/editor/common/languageFeatureRegistry'; -import { CodeActionProvider, CodeLensProvider, CompletionItemProvider, DocumentPasteEditProvider, DeclarationProvider, DefinitionProvider, DocumentColorProvider, DocumentFormattingEditProvider, DocumentHighlightProvider, DocumentOnDropEditProvider, DocumentRangeFormattingEditProvider, DocumentRangeSemanticTokensProvider, DocumentSemanticTokensProvider, DocumentSymbolProvider, EvaluatableExpressionProvider, FoldingRangeProvider, HoverProvider, ImplementationProvider, InlayHintsProvider, InlineCompletionsProvider, InlineValuesProvider, LinkedEditingRangeProvider, LinkProvider, OnTypeFormattingEditProvider, ReferenceProvider, RenameProvider, SelectionRangeProvider, SignatureHelpProvider, TypeDefinitionProvider } from 'vs/editor/common/languages'; +import { CodeActionProvider, CodeLensProvider, CompletionItemProvider, DocumentPasteEditProvider, DeclarationProvider, DefinitionProvider, DocumentColorProvider, DocumentFormattingEditProvider, DocumentHighlightProvider, DocumentOnDropEditProvider, DocumentRangeFormattingEditProvider, DocumentRangeSemanticTokensProvider, DocumentSemanticTokensProvider, DocumentSymbolProvider, EvaluatableExpressionProvider, FoldingRangeProvider, HoverProvider, ImplementationProvider, InlayHintsProvider, InlineCompletionsProvider, InlineValuesProvider, LinkedEditingRangeProvider, LinkProvider, OnTypeFormattingEditProvider, ReferenceProvider, RenameProvider, SelectionRangeProvider, SignatureHelpProvider, TypeDefinitionProvider, MappedEditsProvider } from 'vs/editor/common/languages'; import { ILanguageFeaturesService } from 'vs/editor/common/services/languageFeatures'; import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions'; @@ -42,6 +42,7 @@ export class LanguageFeaturesService implements ILanguageFeaturesService { readonly documentSemanticTokensProvider = new LanguageFeatureRegistry(this._score.bind(this)); readonly documentOnDropEditProvider = new LanguageFeatureRegistry(this._score.bind(this)); readonly documentPasteEditProvider = new LanguageFeatureRegistry(this._score.bind(this)); + readonly mappedEditsProvider: LanguageFeatureRegistry = new LanguageFeatureRegistry(this._score.bind(this)); private _notebookTypeResolver?: NotebookInfoResolver; diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index 8fbfcd493ae..4d749af6eaf 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -7891,6 +7891,30 @@ declare namespace monaco.languages { provideDocumentRangeSemanticTokens(model: editor.ITextModel, range: Range, token: CancellationToken): ProviderResult; } + export interface RelatedContextItem { + readonly uri: Uri; + readonly range: IRange; + } + + export interface MappedEditsContext { + selections: ISelection[]; + related: RelatedContextItem[]; + } + + export interface MappedEditsProvider { + /** + * Provider maps code blocks from the chat into a workspace edit. + * + * @param document The document to provide mapped edits for. + * @param codeBlocks Code blocks that come from an LLM's reply. + * "Insert at cursor" in the panel chat only sends one edit that the user clicks on, but inline chat can send multiple blocks and let the lang server decide what to do with them. + * @param context The context for providing mapped edits. + * @param token A cancellation token. + * @returns A provider result of text edits. + */ + provideMappedEdits(document: editor.ITextModel, codeBlocks: string[], context: MappedEditsContext, token: CancellationToken): Promise; + } + export interface ILanguageExtensionPoint { id: string; extensions?: string[]; diff --git a/src/vs/workbench/api/browser/extensionHost.contribution.ts b/src/vs/workbench/api/browser/extensionHost.contribution.ts index 6d836e715e1..774cc0cc158 100644 --- a/src/vs/workbench/api/browser/extensionHost.contribution.ts +++ b/src/vs/workbench/api/browser/extensionHost.contribution.ts @@ -86,7 +86,6 @@ import './mainThreadTimeline'; import './mainThreadTesting'; import './mainThreadSecretState'; import './mainThreadShare'; -import './mainThreadMappedEdits'; import './mainThreadProfilContentHandlers'; import './mainThreadSemanticSimilarity'; import './mainThreadIssueReporter'; diff --git a/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts b/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts index 84247a03e27..fb79323e683 100644 --- a/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts +++ b/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts @@ -931,6 +931,13 @@ export class MainThreadLanguageFeatures extends Disposable implements MainThread } return provider.resolveDocumentOnDropFileData(requestId, dataId); } + + // --- mapped edits + + $registerMappedEditsProvider(handle: number, selector: IDocumentFilterDto[]): void { + const provider = new MainThreadMappedEditsProvider(handle, this._proxy, this._uriIdentService); + this._registrations.set(handle, this._languageFeaturesService.mappedEditsProvider.register(selector, provider)); + } } class MainThreadPasteEditProvider implements languages.DocumentPasteEditProvider { @@ -1124,3 +1131,17 @@ export class MainThreadDocumentRangeSemanticTokensProvider implements languages. throw new Error(`Unexpected`); } } + +export class MainThreadMappedEditsProvider implements languages.MappedEditsProvider { + + constructor( + private readonly _handle: number, + private readonly _proxy: ExtHostLanguageFeaturesShape, + private readonly _uriService: IUriIdentityService, + ) { } + + async provideMappedEdits(document: ITextModel, codeBlocks: string[], context: languages.MappedEditsContext, token: CancellationToken): Promise { + const res = await this._proxy.$provideMappedEdits(this._handle, document.uri, codeBlocks, context, token); + return res ? reviveWorkspaceEditDto(res, this._uriService) : null; + } +} diff --git a/src/vs/workbench/api/browser/mainThreadMappedEdits.ts b/src/vs/workbench/api/browser/mainThreadMappedEdits.ts deleted file mode 100644 index a268da7bbe1..00000000000 --- a/src/vs/workbench/api/browser/mainThreadMappedEdits.ts +++ /dev/null @@ -1,57 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { IDisposable, dispose } from 'vs/base/common/lifecycle'; -import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity'; -import { reviveWorkspaceEditDto } from 'vs/workbench/api/browser/mainThreadBulkEdits'; -import { ExtHostContext, ExtHostMappedEditsShape, IDocumentFilterDto, MainContext, MainThreadMappedEditsShape } from 'vs/workbench/api/common/extHost.protocol'; -import { IMappedEditsProvider, IMappedEditsService } from 'vs/workbench/services/mappedEdits/common/mappedEdits'; -import { IExtHostContext, extHostNamedCustomer } from 'vs/workbench/services/extensions/common/extHostCustomers'; - -@extHostNamedCustomer(MainContext.MainThreadMappedEdits) -export class MainThreadMappedEdits implements MainThreadMappedEditsShape { - - private readonly proxy: ExtHostMappedEditsShape; - - private providers = new Map(); - - private providerDisposables = new Map(); - - constructor( - extHostContext: IExtHostContext, - @IMappedEditsService private readonly mappedEditsService: IMappedEditsService, - @IUriIdentityService private readonly uriIdentityService: IUriIdentityService, - ) { - this.proxy = extHostContext.getProxy(ExtHostContext.ExtHostMappedEdits); - } - - $registerMappedEditsProvider(handle: number, selector: IDocumentFilterDto[]): void { - const provider: IMappedEditsProvider = { - selector, - provideMappedEdits: async (document, codeBlocks, context, token) => { - const result = await this.proxy.$provideMappedEdits(handle, document.uri, codeBlocks, context, token); - return result ? reviveWorkspaceEditDto(result, this.uriIdentityService) : null; - } - }; - this.providers.set(handle, provider); - const disposable = this.mappedEditsService.registerMappedEditsProvider(provider); - this.providerDisposables.set(handle, disposable); - } - - $unregisterMappedEditsProvider(handle: number): void { - if (this.providers.has(handle)) { - this.providers.delete(handle); - } - if (this.providerDisposables.has(handle)) { - this.providerDisposables.delete(handle); - } - } - - dispose(): void { - this.providers.clear(); - dispose(this.providerDisposables.values()); - this.providerDisposables.clear(); - } -} diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index 3b77e80ec96..492598f96ff 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -106,7 +106,6 @@ import { IExtHostManagedSockets } from 'vs/workbench/api/common/extHostManagedSo import { ExtHostShare } from 'vs/workbench/api/common/extHostShare'; import { ExtHostChatProvider } from 'vs/workbench/api/common/extHostChatProvider'; import { ExtHostChatSlashCommands } from 'vs/workbench/api/common/extHostChatSlashCommand'; -import { ExtHostMappedEdits } from 'vs/workbench/api/common/extHostMappedEdits'; import { ExtHostChatVariables } from 'vs/workbench/api/common/extHostChatVariables'; export interface IExtensionRegistries { @@ -211,7 +210,6 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I const extHostChatSlashCommands = rpcProtocol.set(ExtHostContext.ExtHostChatSlashCommands, new ExtHostChatSlashCommands(rpcProtocol, extHostChatProvider, extHostLogService)); const extHostChatVariables = rpcProtocol.set(ExtHostContext.ExtHostChatVariables, new ExtHostChatVariables(rpcProtocol)); const extHostChat = rpcProtocol.set(ExtHostContext.ExtHostChat, new ExtHostChat(rpcProtocol, extHostLogService)); - const extHostMappedEdits = rpcProtocol.set(ExtHostContext.ExtHostMappedEdits, new ExtHostMappedEdits(rpcProtocol, extHostDocuments, uriTransformer)); const extHostSemanticSimilarity = rpcProtocol.set(ExtHostContext.ExtHostSemanticSimilarity, new ExtHostSemanticSimilarity(rpcProtocol)); const extHostIssueReporter = rpcProtocol.set(ExtHostContext.ExtHostIssueReporter, new ExtHostIssueReporter(rpcProtocol)); const extHostStatusBar = rpcProtocol.set(ExtHostContext.ExtHostStatusBar, new ExtHostStatusBar(rpcProtocol, extHostCommands.converter)); @@ -1348,7 +1346,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I }, registerMappedEditsProvider(selector: vscode.DocumentSelector, provider: vscode.MappedEditsProvider) { checkProposedApiEnabled(extension, 'mappedEditsProvider'); - return extHostMappedEdits.registerMappedEditsProvider(selector, provider); + return extHostLanguageFeatures.registerMappedEditsProvider(extension, selector, provider); } }; diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index 686e4ad8af6..9e0e46a7578 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -377,7 +377,7 @@ export interface IRelatedContextItemDto { } export interface IMappedEditsContextDto { - selections: ISelection[]; //FIXME@ulugbekna: is this serializable? should I use ISelection? + selections: ISelection[]; related: IRelatedContextItemDto[]; } @@ -436,6 +436,7 @@ export interface MainThreadLanguageFeaturesShape extends IDisposable { $resolvePasteFileData(handle: number, requestId: number, dataId: string): Promise; $resolveDocumentOnDropFileData(handle: number, requestId: number, dataId: string): Promise; $setLanguageConfiguration(handle: number, languageId: string, configuration: ILanguageConfigurationDto): void; + $registerMappedEditsProvider(handle: number, selector: IDocumentFilterDto[]): void; } export interface MainThreadLanguagesShape extends IDisposable { @@ -1325,11 +1326,6 @@ export interface MainThreadShareShape extends IDisposable { $unregisterShareProvider(handle: number): void; } -export interface MainThreadMappedEditsShape extends IDisposable { - $registerMappedEditsProvider(handle: number, selector: IDocumentFilterDto[]): void; - $unregisterMappedEditsProvider(handle: number): void; -} - export interface MainThreadTaskShape extends IDisposable { $createTaskId(task: tasks.ITaskDTO): Promise; $registerTaskProvider(handle: number, type: string): Promise; @@ -2014,6 +2010,7 @@ export interface ExtHostLanguageFeaturesShape { $provideTypeHierarchySubtypes(handle: number, sessionId: string, itemId: string, token: CancellationToken): Promise; $releaseTypeHierarchy(handle: number, sessionId: string): void; $provideDocumentOnDropEdits(handle: number, requestId: number, resource: UriComponents, position: IPosition, dataTransferDto: DataTransferDTO, token: CancellationToken): Promise; + $provideMappedEdits(handle: number, document: UriComponents, codeBlocks: string[], context: IMappedEditsContextDto, token: CancellationToken): Promise; } export interface ExtHostQuickOpenShape { @@ -2113,10 +2110,6 @@ export interface ExtHostShareShape { $provideShare(handle: number, shareableItem: IShareableItemDto, token: CancellationToken): Promise; } -export interface ExtHostMappedEditsShape { - $provideMappedEdits(handle: number, document: UriComponents, codeBlocks: string[], context: IMappedEditsContextDto, token: CancellationToken): Promise; -} - export interface ExtHostTaskShape { $provideTasks(handle: number, validTypes: { [key: string]: boolean }): Promise; $resolveTask(handle: number, taskDTO: tasks.ITaskDTO): Promise; @@ -2642,7 +2635,6 @@ export const MainContext = { MainThreadSCM: createProxyIdentifier('MainThreadSCM'), MainThreadSearch: createProxyIdentifier('MainThreadSearch'), MainThreadShare: createProxyIdentifier('MainThreadShare'), - MainThreadMappedEdits: createProxyIdentifier('MainThreadMappedEdits'), MainThreadTask: createProxyIdentifier('MainThreadTask'), MainThreadWindow: createProxyIdentifier('MainThreadWindow'), MainThreadLabelService: createProxyIdentifier('MainThreadLabelService'), @@ -2720,7 +2712,6 @@ export const ExtHostContext = { ExtHostChatSlashCommands: createProxyIdentifier('ExtHostChatSlashCommands'), ExtHostChatVariables: createProxyIdentifier('ExtHostChatVariables'), ExtHostChatProvider: createProxyIdentifier('ExtHostChatProvider'), - ExtHostMappedEdits: createProxyIdentifier('ExtHostMappedEdits'), ExtHostSemanticSimilarity: createProxyIdentifier('ExtHostSemanticSimilarity'), ExtHostTheming: createProxyIdentifier('ExtHostTheming'), ExtHostTunnelService: createProxyIdentifier('ExtHostTunnelService'), diff --git a/src/vs/workbench/api/common/extHostLanguageFeatures.ts b/src/vs/workbench/api/common/extHostLanguageFeatures.ts index cd8b2c1de2c..ec2fbcebeef 100644 --- a/src/vs/workbench/api/common/extHostLanguageFeatures.ts +++ b/src/vs/workbench/api/common/extHostLanguageFeatures.ts @@ -1817,6 +1817,34 @@ class DocumentOnDropEditAdapter { } } +class MappedEditsAdapter { + + constructor( + private readonly _documents: ExtHostDocuments, + private readonly _provider: vscode.MappedEditsProvider, + ) { } + + async provideMappedEdits( + resource: UriComponents, + codeBlocks: string[], + context: extHostProtocol.IMappedEditsContextDto, + token: CancellationToken + ): Promise { + + const uri = URI.revive(resource); + const doc = this._documents.getDocument(uri); + + const ctx = { + selections: context.selections.map(s => typeConvert.Selection.to(s)), + related: context.related.map(r => ({ uri: URI.revive(r.uri), range: typeConvert.Range.to(r.range) })), + }; + + const mappedEdits = await this._provider.provideMappedEdits(doc, codeBlocks, ctx, token); + + return mappedEdits ? typeConvert.WorkspaceEdit.from(mappedEdits) : null; + } +} + type Adapter = DocumentSymbolAdapter | CodeLensAdapter | DefinitionAdapter | HoverAdapter | DocumentHighlightAdapter | ReferenceAdapter | CodeActionAdapter | DocumentPasteEditProvider | DocumentFormattingAdapter | RangeFormattingAdapter | OnTypeFormattingAdapter | NavigateTypeAdapter | RenameAdapter @@ -1826,7 +1854,7 @@ type Adapter = DocumentSymbolAdapter | CodeLensAdapter | DefinitionAdapter | Hov | DocumentSemanticTokensAdapter | DocumentRangeSemanticTokensAdapter | EvaluatableExpressionAdapter | InlineValuesAdapter | LinkedEditingRangeAdapter | InlayHintsAdapter | InlineCompletionAdapter - | DocumentOnDropEditAdapter; + | DocumentOnDropEditAdapter | MappedEditsAdapter; class AdapterData { constructor( @@ -2383,7 +2411,14 @@ export class ExtHostLanguageFeatures implements extHostProtocol.ExtHostLanguageF } $provideFoldingRanges(handle: number, resource: UriComponents, context: vscode.FoldingContext, token: CancellationToken): Promise { - return this._withAdapter(handle, FoldingProviderAdapter, adapter => adapter.provideFoldingRanges(URI.revive(resource), context, token), undefined, token); + return this._withAdapter( + handle, + FoldingProviderAdapter, + (adapter) => + adapter.provideFoldingRanges(URI.revive(resource), context, token), + undefined, + token + ); } // --- smart select @@ -2462,6 +2497,19 @@ export class ExtHostLanguageFeatures implements extHostProtocol.ExtHostLanguageF Promise.resolve(adapter.provideDocumentOnDropEdits(requestId, URI.revive(resource), position, dataTransferDto, token)), undefined, undefined); } + // --- mapped edits + + registerMappedEditsProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.MappedEditsProvider): vscode.Disposable { + const handle = this._addNewAdapter(new MappedEditsAdapter(this._documents, provider), extension); + this._proxy.$registerMappedEditsProvider(handle, this._transformDocumentSelector(selector, extension)); + return this._createDisposable(handle); + } + + $provideMappedEdits(handle: number, document: UriComponents, codeBlocks: string[], context: extHostProtocol.IMappedEditsContextDto, token: CancellationToken): Promise { + return this._withAdapter(handle, MappedEditsAdapter, adapter => + Promise.resolve(adapter.provideMappedEdits(document, codeBlocks, context, token)), null, token); + } + // --- copy/paste actions registerDocumentPasteEditProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.DocumentPasteEditProvider, metadata: vscode.DocumentPasteProviderMetadata): vscode.Disposable { diff --git a/src/vs/workbench/api/common/extHostMappedEdits.ts b/src/vs/workbench/api/common/extHostMappedEdits.ts deleted file mode 100644 index c98adda03b2..00000000000 --- a/src/vs/workbench/api/common/extHostMappedEdits.ts +++ /dev/null @@ -1,61 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { CancellationToken } from 'vs/base/common/cancellation'; -import { URI, UriComponents } from 'vs/base/common/uri'; -import { IURITransformer } from 'vs/base/common/uriIpc'; -import { ExtHostMappedEditsShape, IMainContext, IMappedEditsContextDto, IWorkspaceEditDto, MainContext, MainThreadMappedEditsShape } from 'vs/workbench/api/common/extHost.protocol'; -import { ExtHostDocuments } from 'vs/workbench/api/common/extHostDocuments'; -import { Range, Selection, DocumentSelector, WorkspaceEdit } from 'vs/workbench/api/common/extHostTypeConverters'; -import type * as vscode from 'vscode'; - -export class ExtHostMappedEdits implements ExtHostMappedEditsShape { - - private static handlePool: number = 0; - - private proxy: MainThreadMappedEditsShape; - private providers = new Map(); - - constructor( - mainContext: IMainContext, - private readonly _documents: ExtHostDocuments, - private readonly uriTransformer: IURITransformer | undefined - ) { - this.proxy = mainContext.getProxy(MainContext.MainThreadMappedEdits); - } - - async $provideMappedEdits(handle: number, docUri: UriComponents, codeBlocks: string[], context: IMappedEditsContextDto, token: CancellationToken): Promise { - const provider = this.providers.get(handle); - if (!provider) { - return null; - } - const uri = URI.revive(docUri); - const doc = this._documents.getDocument(uri); - const ctx = { - selections: context.selections.map(s => Selection.to(s)), - related: context.related.map(r => ({ uri: URI.revive(r.uri), range: Range.to(r.range) })), - }; - const mappedEdits = await provider.provideMappedEdits(doc, codeBlocks, ctx, token); - if (!mappedEdits) { - return null; - } - - return WorkspaceEdit.from(mappedEdits); - } - - registerMappedEditsProvider(selector: vscode.DocumentSelector, provider: vscode.MappedEditsProvider): vscode.Disposable { - const handle = ExtHostMappedEdits.handlePool++; - this.providers.set(handle, provider); - this.proxy.$registerMappedEditsProvider(handle, DocumentSelector.from(selector, this.uriTransformer)); - return { - dispose: () => { - ExtHostMappedEdits.handlePool--; - this.proxy.$unregisterMappedEditsProvider(handle); - this.providers.delete(handle); - } - }; - } - -} diff --git a/src/vs/workbench/api/common/extHostTypeConverters.ts b/src/vs/workbench/api/common/extHostTypeConverters.ts index 0f7efee2be4..e745869c9cf 100644 --- a/src/vs/workbench/api/common/extHostTypeConverters.ts +++ b/src/vs/workbench/api/common/extHostTypeConverters.ts @@ -32,7 +32,6 @@ import { IMarkerData, IRelatedInformation, MarkerSeverity, MarkerTag } from 'vs/ import { ProgressLocation as MainProgressLocation } from 'vs/platform/progress/common/progress'; import * as extHostProtocol from 'vs/workbench/api/common/extHost.protocol'; import { getPrivateApiFor } from 'vs/workbench/api/common/extHostTestingPrivateApi'; -import type * as mappedEdits from 'vs/workbench/services/mappedEdits/common/mappedEdits'; import { DEFAULT_EDITOR_ASSOCIATION, SaveReason } from 'vs/workbench/common/editor'; import { IViewBadge } from 'vs/workbench/common/views'; import { IChatFollowup, IChatReplyFollowup, IChatResponseCommandFollowup } from 'vs/workbench/contrib/chat/common/chatService'; @@ -1577,10 +1576,10 @@ export namespace MappedEditsContext { v.related.every(e => e && typeof e === 'object' && URI.isUri(e.uri) && e.range instanceof types.Range)); } - export function from(context: vscode.MappedEditsContext): mappedEdits.MappedEditsContext { + export function from(extContext: vscode.MappedEditsContext): languages.MappedEditsContext { return { - selections: context.selections.map(s => Selection.from(s)), - related: context.related.map(r => ({ + selections: extContext.selections.map(s => Selection.from(s)), + related: extContext.related.map(r => ({ uri: URI.from(r.uri), range: Range.from(r.range) })) diff --git a/src/vs/workbench/contrib/chat/browser/actions/chatCodeblockActions.ts b/src/vs/workbench/contrib/chat/browser/actions/chatCodeblockActions.ts index 85fd1ee7ad2..3761e137dc5 100644 --- a/src/vs/workbench/contrib/chat/browser/actions/chatCodeblockActions.ts +++ b/src/vs/workbench/contrib/chat/browser/actions/chatCodeblockActions.ts @@ -25,13 +25,14 @@ import { IChatWidgetService } from 'vs/workbench/contrib/chat/browser/chat'; import { CONTEXT_IN_CHAT_SESSION, CONTEXT_PROVIDER_EXISTS } from 'vs/workbench/contrib/chat/common/chatContextKeys'; import { IChatCopyAction, IChatService, IChatUserActionEvent, InteractiveSessionCopyKind } from 'vs/workbench/contrib/chat/common/chatService'; import { IChatResponseViewModel, isResponseVM } from 'vs/workbench/contrib/chat/common/chatViewModel'; -import { IMappedEditsService, RelatedContextItem } from 'vs/workbench/services/mappedEdits/common/mappedEdits'; import { insertCell } from 'vs/workbench/contrib/notebook/browser/controller/cellOperations'; import { INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { CellKind, NOTEBOOK_EDITOR_ID } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { ITerminalEditorService, ITerminalGroupService, ITerminalService } from 'vs/workbench/contrib/terminal/browser/terminal'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; +import { ILanguageFeaturesService } from 'vs/editor/common/services/languageFeatures'; +import { WorkspaceEdit, RelatedContextItem } from 'vs/editor/common/languages'; export interface IChatCodeBlockActionContext { code: string; @@ -236,19 +237,33 @@ export function registerChatCodeBlockActions() { private async handleTextEditor(accessor: ServicesAccessor, codeEditor: ICodeEditor, activeModel: ITextModel, chatCodeBlockActionContext: IChatCodeBlockActionContext) { this.notifyUserAction(accessor, chatCodeBlockActionContext); + const bulkEditService = accessor.get(IBulkEditService); const codeEditorService = accessor.get(ICodeEditorService); - const mappedEditsService = accessor.get(IMappedEditsService); + + const mappedEditsProviders = accessor.get(ILanguageFeaturesService).mappedEditsProvider.ordered(activeModel); // try applying workspace edit that was returned by a MappedEditsProvider, else simply insert at selection - const selections = codeEditor.getSelections() ?? []; - const mappedEditsContext = { - selections, - related: [] as RelatedContextItem[], // FIXME@ulugbekna: this needs to be populated but we don't yet have a way to get this info from extensions - }; - const cancellationTokenSource = new CancellationTokenSource(); - const workspaceEdit = await mappedEditsService.provideMappedEdits(activeModel, [chatCodeBlockActionContext.code], mappedEditsContext, cancellationTokenSource.token); + let workspaceEdit: WorkspaceEdit | null = null; + + if (mappedEditsProviders.length > 0) { + const mostRelevantProvider = mappedEditsProviders[0]; + + const selections = codeEditor.getSelections() ?? []; + const mappedEditsContext = { + selections, + related: [] as RelatedContextItem[], // TODO@ulugbekna: we do have not yet decided what to populate this with + }; + const cancellationTokenSource = new CancellationTokenSource(); + + workspaceEdit = await mostRelevantProvider.provideMappedEdits( + activeModel, + [chatCodeBlockActionContext.code], + mappedEditsContext, + cancellationTokenSource.token); + } + if (workspaceEdit) { await bulkEditService.apply(workspaceEdit); } else { diff --git a/src/vs/workbench/contrib/mappedEdits/common/mappedEdits.contribution.ts b/src/vs/workbench/contrib/mappedEdits/common/mappedEdits.contribution.ts index 82171c7fbed..fc753a4b673 100644 --- a/src/vs/workbench/contrib/mappedEdits/common/mappedEdits.contribution.ts +++ b/src/vs/workbench/contrib/mappedEdits/common/mappedEdits.contribution.ts @@ -5,23 +5,47 @@ import { CancellationTokenSource } from 'vs/base/common/cancellation'; import { URI } from 'vs/base/common/uri'; +import { ILanguageFeaturesService } from 'vs/editor/common/services/languageFeatures'; import { ITextModelService } from 'vs/editor/common/services/resolverService'; import { CommandsRegistry } from 'vs/platform/commands/common/commands'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; -import { IMappedEditsService, MappedEditsContext } from 'vs/workbench/services/mappedEdits/common/mappedEdits'; +import * as languages from 'vs/editor/common/languages'; -CommandsRegistry.registerCommand('_executeMappedEditsProvider', async (accessor: ServicesAccessor, documentUri: URI, codeBlocks: string[], context: MappedEditsContext) => { +CommandsRegistry.registerCommand( + '_executeMappedEditsProvider', + async ( + accessor: ServicesAccessor, + documentUri: URI, + codeBlocks: string[], + context: languages.MappedEditsContext + ): Promise => { - const mappedEditsService = accessor.get(IMappedEditsService); - const modelService = accessor.get(ITextModelService); + const modelService = accessor.get(ITextModelService); + const langFeaturesService = accessor.get(ILanguageFeaturesService); - const document = await modelService.createModelReference(documentUri); + const document = await modelService.createModelReference(documentUri); - const cancellationTokenSource = new CancellationTokenSource(); + let result: languages.WorkspaceEdit | null = null; - const result = await mappedEditsService.provideMappedEdits(document.object.textEditorModel, codeBlocks, context, cancellationTokenSource.token); + try { + const providers = langFeaturesService.mappedEditsProvider.ordered(document.object.textEditorModel); - document.dispose(); + if (providers.length > 0) { + const mostRelevantProvider = providers[0]; - return result; -}); + const cancellationTokenSource = new CancellationTokenSource(); + + result = await mostRelevantProvider.provideMappedEdits( + document.object.textEditorModel, + codeBlocks, + context, + cancellationTokenSource.token + ); + } + } finally { + document.dispose(); + } + + return result; + } +); diff --git a/src/vs/workbench/services/mappedEdits/browser/mappedEditsService.ts b/src/vs/workbench/services/mappedEdits/browser/mappedEditsService.ts deleted file mode 100644 index fe1cec5815a..00000000000 --- a/src/vs/workbench/services/mappedEdits/browser/mappedEditsService.ts +++ /dev/null @@ -1,51 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { CancellationToken } from 'vs/base/common/cancellation'; -import { ITextModel } from 'vs/editor/common/model'; -import { IMappedEditsProvider, IMappedEditsService, MappedEditsContext } from 'vs/workbench/services/mappedEdits/common/mappedEdits'; -import { score } from 'vs/editor/common/languageSelector'; -import { WorkspaceEdit } from 'vs/editor/common/languages'; -import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions'; - -export class MappedEditsService implements IMappedEditsService { - readonly _serviceBrand: undefined; - - private readonly _providers = new Set(); - - constructor() { } - - registerMappedEditsProvider(provider: IMappedEditsProvider) { - this._providers.add(provider); - return { - dispose: () => { - this._providers.delete(provider); - } - }; - } - - async provideMappedEdits(document: ITextModel, codeBlocks: string[], context: MappedEditsContext, token: CancellationToken): Promise { - - const language = document.getLanguageId(); - - const providers = [...this._providers.values()] - .map((p): [IMappedEditsProvider, number] => { - const pts = score(p.selector, document.uri, language, true, undefined, undefined); - return [p, pts]; - }) - .filter(([p, pts]) => pts > 0) - .sort((a, b) => b[1] - a[1]); - - if (providers.length === 0) { - return null; - } - - const provider = providers[0][0]; - - return provider.provideMappedEdits(document, codeBlocks, context, token); - } -} - -registerSingleton(IMappedEditsService, MappedEditsService, InstantiationType.Delayed); diff --git a/src/vs/workbench/services/mappedEdits/common/mappedEdits.ts b/src/vs/workbench/services/mappedEdits/common/mappedEdits.ts deleted file mode 100644 index 9a60304881c..00000000000 --- a/src/vs/workbench/services/mappedEdits/common/mappedEdits.ts +++ /dev/null @@ -1,65 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { URI } from 'vs/base/common/uri'; -import { ITextModel } from 'vs/editor/common/model'; -import { CancellationToken } from 'vs/base/common/cancellation'; -import { LanguageSelector } from 'vs/editor/common/languageSelector'; -import { IDisposable } from 'vs/base/common/lifecycle'; -import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; -import { WorkspaceEdit } from 'vs/editor/common/languages'; -import { ISelection } from 'vs/editor/common/core/selection'; -import { IRange } from 'vs/editor/common/core/range'; - -export interface RelatedContextItem { - readonly uri: URI; - readonly range: IRange; -} - -export interface MappedEditsContext { - selections: ISelection[]; - - /** - * If there's no context, the array should be empty. It's also empty until we figure out how to compute this or retrieve from an extension (eg, copilot chat) - * - * TODO@ulugbekna: should this array be sorted from highest priority to lowest? - */ - related: RelatedContextItem[]; -} - -export interface IMappedEditsProvider { - - selector: LanguageSelector; - - /** - * Provide mapped edits for a given document. - * - * @param document The document to provide mapped edits for. - * @param codeBlocks Code blocks that come from an LLM's reply. - * "Insert at cursor" in the panel chat only sends one edit that the user clicks on, but inline chat can send multiple blocks and let the lang server decide what to do with them. - * @param context The context for providing mapped edits. - * @param token A cancellation token. - * @returns A provider result of text edits. - */ - provideMappedEdits( - document: ITextModel, - codeBlocks: string[], - context: MappedEditsContext, - token: CancellationToken - ): Promise; -} - - -export const IMappedEditsService = createDecorator('mappedEditsService'); - -export interface IMappedEditsService { - _serviceBrand: undefined; - registerMappedEditsProvider(provider: IMappedEditsProvider): IDisposable; - provideMappedEdits( - document: ITextModel, - codeBlocks: string[], - context: MappedEditsContext, - token: CancellationToken): Promise; -} diff --git a/src/vs/workbench/workbench.common.main.ts b/src/vs/workbench/workbench.common.main.ts index d30cd73ec49..98d5a3cc130 100644 --- a/src/vs/workbench/workbench.common.main.ts +++ b/src/vs/workbench/workbench.common.main.ts @@ -111,7 +111,6 @@ import 'vs/workbench/services/textMate/browser/textMateTokenizationFeature.contr import 'vs/workbench/services/userActivity/common/userActivityService'; import 'vs/workbench/services/userActivity/browser/userActivityBrowser'; import 'vs/workbench/services/issue/browser/issueTroubleshoot'; -import 'vs/workbench/services/mappedEdits/browser/mappedEditsService'; import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { ExtensionGalleryService } from 'vs/platform/extensionManagement/common/extensionGalleryService'; From 7705edf96cd90eec4a0df8de811d1400ee796088 Mon Sep 17 00:00:00 2001 From: Ulugbek Abdullaev Date: Tue, 22 Aug 2023 15:56:54 +0200 Subject: [PATCH 076/221] add `null` as possible return type for the `vscode.executeMappedEditsProvider` --- src/vs/workbench/api/common/extHostApiCommands.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/api/common/extHostApiCommands.ts b/src/vs/workbench/api/common/extHostApiCommands.ts index fdb8ffa2cd6..84545808c0f 100644 --- a/src/vs/workbench/api/common/extHostApiCommands.ts +++ b/src/vs/workbench/api/common/extHostApiCommands.ts @@ -478,10 +478,10 @@ const newCommands: ApiCommand[] = [ (v: vscode.MappedEditsContext) => typeConverters.MappedEditsContext.from(v) ) ], - new ApiCommandResult( + new ApiCommandResult( 'A promise that resolves to a workspace edit or null', (value) => { - return typeConverters.WorkspaceEdit.to(value); + return value ? typeConverters.WorkspaceEdit.to(value) : null; }) ), ]; From fe52b50e41878a5b6dcbc20a7d755fc840441841 Mon Sep 17 00:00:00 2001 From: Ulugbek Abdullaev Date: Tue, 22 Aug 2023 15:57:40 +0200 Subject: [PATCH 077/221] add `mappedEditsProvider` proposed API ID to integration tests' package.json --- extensions/vscode-api-tests/package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/extensions/vscode-api-tests/package.json b/extensions/vscode-api-tests/package.json index 5ee95741ff0..9d50e393547 100644 --- a/extensions/vscode-api-tests/package.json +++ b/extensions/vscode-api-tests/package.json @@ -19,6 +19,7 @@ "fileSearchProvider", "findTextInFiles", "fsChunks", + "mappedEditsProvider", "notebookCellExecutionState", "notebookDeprecated", "notebookLiveShare", @@ -45,7 +46,7 @@ "timeline", "tokenInformation", "treeItemCheckbox", - "treeViewActiveItem", + "treeViewActiveItem", "treeViewReveal", "workspaceTrust", "telemetry", From 7ab8588219218584983484d813e663d80db190cc Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Tue, 22 Aug 2023 07:45:18 -0700 Subject: [PATCH 078/221] xterm@5.3.0-beta.58 Fixes #189684 Part of #190195 (diagnostics) --- package.json | 16 +++++------ remote/package.json | 16 +++++------ remote/web/package.json | 12 ++++---- remote/web/yarn.lock | 48 +++++++++++++++---------------- remote/yarn.lock | 64 ++++++++++++++++++++--------------------- yarn.lock | 64 ++++++++++++++++++++--------------------- 6 files changed, 110 insertions(+), 110 deletions(-) diff --git a/package.json b/package.json index 7c5d9cb3444..b878c99812b 100644 --- a/package.json +++ b/package.json @@ -95,14 +95,14 @@ "vscode-oniguruma": "1.7.0", "vscode-regexpp": "^3.1.0", "vscode-textmate": "9.0.0", - "xterm": "5.3.0-beta.46", - "xterm-addon-canvas": "0.5.0-beta.9", - "xterm-addon-image": "0.6.0-beta.2", - "xterm-addon-search": "0.13.0-beta.8", - "xterm-addon-serialize": "0.11.0-beta.8", - "xterm-addon-unicode11": "0.5.0", - "xterm-addon-webgl": "0.16.0-beta.16", - "xterm-headless": "5.3.0-beta.46", + "xterm": "5.3.0-beta.58", + "xterm-addon-canvas": "0.5.0-beta.19", + "xterm-addon-image": "0.6.0-beta.11", + "xterm-addon-search": "0.13.0-beta.17", + "xterm-addon-serialize": "0.11.0-beta.17", + "xterm-addon-unicode11": "0.6.0-beta.9", + "xterm-addon-webgl": "0.16.0-beta.27", + "xterm-headless": "5.3.0-beta.58", "yauzl": "^2.9.2", "yazl": "^2.4.3" }, diff --git a/remote/package.json b/remote/package.json index 28cf60a0252..6d6a0152a55 100644 --- a/remote/package.json +++ b/remote/package.json @@ -27,14 +27,14 @@ "vscode-oniguruma": "1.7.0", "vscode-regexpp": "^3.1.0", "vscode-textmate": "9.0.0", - "xterm": "5.3.0-beta.46", - "xterm-addon-canvas": "0.5.0-beta.9", - "xterm-addon-image": "0.6.0-beta.2", - "xterm-addon-search": "0.13.0-beta.8", - "xterm-addon-serialize": "0.11.0-beta.8", - "xterm-addon-unicode11": "0.5.0", - "xterm-addon-webgl": "0.16.0-beta.16", - "xterm-headless": "5.3.0-beta.46", + "xterm": "5.3.0-beta.58", + "xterm-addon-canvas": "0.5.0-beta.19", + "xterm-addon-image": "0.6.0-beta.11", + "xterm-addon-search": "0.13.0-beta.17", + "xterm-addon-serialize": "0.11.0-beta.17", + "xterm-addon-unicode11": "0.6.0-beta.9", + "xterm-addon-webgl": "0.16.0-beta.27", + "xterm-headless": "5.3.0-beta.58", "yauzl": "^2.9.2", "yazl": "^2.4.3" } diff --git a/remote/web/package.json b/remote/web/package.json index bd22a24243a..05686230a43 100644 --- a/remote/web/package.json +++ b/remote/web/package.json @@ -11,11 +11,11 @@ "tas-client-umd": "0.1.8", "vscode-oniguruma": "1.7.0", "vscode-textmate": "9.0.0", - "xterm": "5.3.0-beta.46", - "xterm-addon-canvas": "0.5.0-beta.9", - "xterm-addon-image": "0.6.0-beta.2", - "xterm-addon-search": "0.13.0-beta.8", - "xterm-addon-unicode11": "0.5.0", - "xterm-addon-webgl": "0.16.0-beta.16" + "xterm": "5.3.0-beta.58", + "xterm-addon-canvas": "0.5.0-beta.19", + "xterm-addon-image": "0.6.0-beta.11", + "xterm-addon-search": "0.13.0-beta.17", + "xterm-addon-unicode11": "0.6.0-beta.9", + "xterm-addon-webgl": "0.16.0-beta.27" } } diff --git a/remote/web/yarn.lock b/remote/web/yarn.lock index b57b5aa165d..dc817e45bf1 100644 --- a/remote/web/yarn.lock +++ b/remote/web/yarn.lock @@ -68,32 +68,32 @@ vscode-textmate@9.0.0: resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-9.0.0.tgz#313c6c8792b0507aef35aeb81b6b370b37c44d6c" integrity sha512-Cl65diFGxz7gpwbav10HqiY/eVYTO1sjQpmRmV991Bj7wAoOAjGQ97PpQcXorDE2Uc4hnGWLY17xme+5t6MlSg== -xterm-addon-canvas@0.5.0-beta.9: - version "0.5.0-beta.9" - resolved "https://registry.yarnpkg.com/xterm-addon-canvas/-/xterm-addon-canvas-0.5.0-beta.9.tgz#d4a9536cf586f78a54527751e03abf6445613886" - integrity sha512-AMyFctHbIWx0aLcACINuZqFFNoz4ndGtIAb4pQguIl9t8r+2otiV11MY4FJmPM0kUzEzoLWzVFJaGxOzykCWuw== +xterm-addon-canvas@0.5.0-beta.19: + version "0.5.0-beta.19" + resolved "https://registry.yarnpkg.com/xterm-addon-canvas/-/xterm-addon-canvas-0.5.0-beta.19.tgz#a2b67554191fae29c901c4a4b398fc28dc345afe" + integrity sha512-eF6b7SBZslmwqCLiWTGnjna4bdjd28cQ+ivZH8SVjE5xP3JGAHGWs/fZm5E3eR6pcHEOkX++/FxByuvhOVXIXQ== -xterm-addon-image@0.6.0-beta.2: - version "0.6.0-beta.2" - resolved "https://registry.yarnpkg.com/xterm-addon-image/-/xterm-addon-image-0.6.0-beta.2.tgz#04c5ea11c89032b01b577b37f891109168ed0b09" - integrity sha512-58d1mqIpJwq8Zy/a/QM8JVuA1g5SceG8UvLoj9T6r+2XIktka6GK2oS66Fmo+0MP0s0HDPy+yJtl8lHY6UyzHw== +xterm-addon-image@0.6.0-beta.11: + version "0.6.0-beta.11" + resolved "https://registry.yarnpkg.com/xterm-addon-image/-/xterm-addon-image-0.6.0-beta.11.tgz#17dffc5f38480a4fac231649ef6e313a8f46d614" + integrity sha512-KPsqJo8sSAawO4ze7xvjtS5evbPtlscy16NiSAteh/1AgOffmTnVhJTs3W84dnks2b13FaMEI/WOiCDIJjDV3A== -xterm-addon-search@0.13.0-beta.8: - version "0.13.0-beta.8" - resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.13.0-beta.8.tgz#90bc70bff87cd7e4f540cce51d9f968f04d5c0ef" - integrity sha512-Hlocg6gGvKAs4eRTW78wTtVqaOEurweJjdyPDjr7KrzwlEEsASsUXJaB2+vgsyTFKuYnCuLrp5u369jck993GQ== +xterm-addon-search@0.13.0-beta.17: + version "0.13.0-beta.17" + resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.13.0-beta.17.tgz#5379cf3085370c55241d99e95b008c0cbf4e6e53" + integrity sha512-0OKwV9isk4OXHLlhRE8Ohqnmpcd0ExWKtorjeaFxqm4f6xc30qZcJTs0hSMzVZ83foedPJcd6hH0hW2pnxOz3Q== -xterm-addon-unicode11@0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/xterm-addon-unicode11/-/xterm-addon-unicode11-0.5.0.tgz#41c0d96acc1e3bb6c6596eee64e163b6bca74be7" - integrity sha512-Jm4/g4QiTxiKiTbYICQgC791ubhIZyoIwxAIgOW8z8HWFNY+lwk+dwaKEaEeGBfM48Vk8fklsUW9u/PlenYEBg== +xterm-addon-unicode11@0.6.0-beta.9: + version "0.6.0-beta.9" + resolved "https://registry.yarnpkg.com/xterm-addon-unicode11/-/xterm-addon-unicode11-0.6.0-beta.9.tgz#1f476f77cf8c8e4e7ca1a1421b85ac45405db679" + integrity sha512-DH9OIH0EakIdCnzZcIH7NLgUqXwa8WT9fqmi+2CWzt4NN1AH5kSE/3Vk+/uurE5upxDloKw6dtLH9XHpfULV6g== -xterm-addon-webgl@0.16.0-beta.16: - version "0.16.0-beta.16" - resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.16.0-beta.16.tgz#2c31308f8c7f636576720adca529297f8fff3224" - integrity sha512-k0ZSwpBVtxXaqUc29CmlfFgIK7LEYAmwcDC3QVp2ESZo2JHYuQrWFpImjbzbYu0ON6qqcfbX8SnbzRid/XfGUg== +xterm-addon-webgl@0.16.0-beta.27: + version "0.16.0-beta.27" + resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.16.0-beta.27.tgz#f4133a40044f0b6448ea87152abf6c9009729100" + integrity sha512-YiwCvTvgfcNGtQdpzcgxKINE6mG63cPfDxfoxCAbodNGYF66k9VzhIXNdCQtVtu+s6+pEc9YequENe78SSZloA== -xterm@5.3.0-beta.46: - version "5.3.0-beta.46" - resolved "https://registry.yarnpkg.com/xterm/-/xterm-5.3.0-beta.46.tgz#9bd2b2a588c88ae64f1989ca3bf5bd9116554b5a" - integrity sha512-keB3C6sXm56ug1+hylAQiNyZP4YtPgd2W+Gu/ZKwJMk5haD25DEnenBYL++Cl3+sNGYxOGS42QlmYj6Mrq1LPw== +xterm@5.3.0-beta.58: + version "5.3.0-beta.58" + resolved "https://registry.yarnpkg.com/xterm/-/xterm-5.3.0-beta.58.tgz#4bae06639c90952b270e4714938c151ce339b5f0" + integrity sha512-EIOgp+7aqCToI0XjDqORXAe2lJS/XSZXWPzCpyTDmF+DJ56gyw+913gdPoIEWOw3mRylrJtEyIpFcdW7CDA6rQ== diff --git a/remote/yarn.lock b/remote/yarn.lock index e222314587d..68c99905917 100644 --- a/remote/yarn.lock +++ b/remote/yarn.lock @@ -877,45 +877,45 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= -xterm-addon-canvas@0.5.0-beta.9: - version "0.5.0-beta.9" - resolved "https://registry.yarnpkg.com/xterm-addon-canvas/-/xterm-addon-canvas-0.5.0-beta.9.tgz#d4a9536cf586f78a54527751e03abf6445613886" - integrity sha512-AMyFctHbIWx0aLcACINuZqFFNoz4ndGtIAb4pQguIl9t8r+2otiV11MY4FJmPM0kUzEzoLWzVFJaGxOzykCWuw== +xterm-addon-canvas@0.5.0-beta.19: + version "0.5.0-beta.19" + resolved "https://registry.yarnpkg.com/xterm-addon-canvas/-/xterm-addon-canvas-0.5.0-beta.19.tgz#a2b67554191fae29c901c4a4b398fc28dc345afe" + integrity sha512-eF6b7SBZslmwqCLiWTGnjna4bdjd28cQ+ivZH8SVjE5xP3JGAHGWs/fZm5E3eR6pcHEOkX++/FxByuvhOVXIXQ== -xterm-addon-image@0.6.0-beta.2: - version "0.6.0-beta.2" - resolved "https://registry.yarnpkg.com/xterm-addon-image/-/xterm-addon-image-0.6.0-beta.2.tgz#04c5ea11c89032b01b577b37f891109168ed0b09" - integrity sha512-58d1mqIpJwq8Zy/a/QM8JVuA1g5SceG8UvLoj9T6r+2XIktka6GK2oS66Fmo+0MP0s0HDPy+yJtl8lHY6UyzHw== +xterm-addon-image@0.6.0-beta.11: + version "0.6.0-beta.11" + resolved "https://registry.yarnpkg.com/xterm-addon-image/-/xterm-addon-image-0.6.0-beta.11.tgz#17dffc5f38480a4fac231649ef6e313a8f46d614" + integrity sha512-KPsqJo8sSAawO4ze7xvjtS5evbPtlscy16NiSAteh/1AgOffmTnVhJTs3W84dnks2b13FaMEI/WOiCDIJjDV3A== -xterm-addon-search@0.13.0-beta.8: - version "0.13.0-beta.8" - resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.13.0-beta.8.tgz#90bc70bff87cd7e4f540cce51d9f968f04d5c0ef" - integrity sha512-Hlocg6gGvKAs4eRTW78wTtVqaOEurweJjdyPDjr7KrzwlEEsASsUXJaB2+vgsyTFKuYnCuLrp5u369jck993GQ== +xterm-addon-search@0.13.0-beta.17: + version "0.13.0-beta.17" + resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.13.0-beta.17.tgz#5379cf3085370c55241d99e95b008c0cbf4e6e53" + integrity sha512-0OKwV9isk4OXHLlhRE8Ohqnmpcd0ExWKtorjeaFxqm4f6xc30qZcJTs0hSMzVZ83foedPJcd6hH0hW2pnxOz3Q== -xterm-addon-serialize@0.11.0-beta.8: - version "0.11.0-beta.8" - resolved "https://registry.yarnpkg.com/xterm-addon-serialize/-/xterm-addon-serialize-0.11.0-beta.8.tgz#343357aad7c549a37aacac2fb19692b1c2fd69cd" - integrity sha512-1jNrX+Y8dorWtjMvz02mRUP+ahqQ4STO0lYlKe8m06p+NYuFk24CylnPZFuBgk91OUU3RAdl4glaKh5M4f0/Zw== +xterm-addon-serialize@0.11.0-beta.17: + version "0.11.0-beta.17" + resolved "https://registry.yarnpkg.com/xterm-addon-serialize/-/xterm-addon-serialize-0.11.0-beta.17.tgz#170738ab615e2974c593d41531d41c02b8af1da7" + integrity sha512-zNsUQfIbRD8fL0gHGJJ14DXL22Kduv6pR+QnISReoQqhEEsWANPKpOduJLce7B4y+BJuiOGkT7R7qbMKbj9Ecw== -xterm-addon-unicode11@0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/xterm-addon-unicode11/-/xterm-addon-unicode11-0.5.0.tgz#41c0d96acc1e3bb6c6596eee64e163b6bca74be7" - integrity sha512-Jm4/g4QiTxiKiTbYICQgC791ubhIZyoIwxAIgOW8z8HWFNY+lwk+dwaKEaEeGBfM48Vk8fklsUW9u/PlenYEBg== +xterm-addon-unicode11@0.6.0-beta.9: + version "0.6.0-beta.9" + resolved "https://registry.yarnpkg.com/xterm-addon-unicode11/-/xterm-addon-unicode11-0.6.0-beta.9.tgz#1f476f77cf8c8e4e7ca1a1421b85ac45405db679" + integrity sha512-DH9OIH0EakIdCnzZcIH7NLgUqXwa8WT9fqmi+2CWzt4NN1AH5kSE/3Vk+/uurE5upxDloKw6dtLH9XHpfULV6g== -xterm-addon-webgl@0.16.0-beta.16: - version "0.16.0-beta.16" - resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.16.0-beta.16.tgz#2c31308f8c7f636576720adca529297f8fff3224" - integrity sha512-k0ZSwpBVtxXaqUc29CmlfFgIK7LEYAmwcDC3QVp2ESZo2JHYuQrWFpImjbzbYu0ON6qqcfbX8SnbzRid/XfGUg== +xterm-addon-webgl@0.16.0-beta.27: + version "0.16.0-beta.27" + resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.16.0-beta.27.tgz#f4133a40044f0b6448ea87152abf6c9009729100" + integrity sha512-YiwCvTvgfcNGtQdpzcgxKINE6mG63cPfDxfoxCAbodNGYF66k9VzhIXNdCQtVtu+s6+pEc9YequENe78SSZloA== -xterm-headless@5.3.0-beta.46: - version "5.3.0-beta.46" - resolved "https://registry.yarnpkg.com/xterm-headless/-/xterm-headless-5.3.0-beta.46.tgz#3f941f673e3c61aad2705e4b34b42fbe467aed48" - integrity sha512-e/VbZKrfyD1TTxOY5/jah3dUih6q8nTO5v5GQV7YOASp+yyI0XHKiDjLrCyFPQOLTKxCcRutMHvr+CoCcPpcHg== +xterm-headless@5.3.0-beta.58: + version "5.3.0-beta.58" + resolved "https://registry.yarnpkg.com/xterm-headless/-/xterm-headless-5.3.0-beta.58.tgz#e6a3dbfafdb28435130ce3925ac3194c0ee2c281" + integrity sha512-ekzr3LX8p26qHDyVRs3lys08veHFv9wGOKaHd49kMgktICHsikJ48HNJq5Twp3ZnXyqlIP9CV34BZJ1SBfWmtQ== -xterm@5.3.0-beta.46: - version "5.3.0-beta.46" - resolved "https://registry.yarnpkg.com/xterm/-/xterm-5.3.0-beta.46.tgz#9bd2b2a588c88ae64f1989ca3bf5bd9116554b5a" - integrity sha512-keB3C6sXm56ug1+hylAQiNyZP4YtPgd2W+Gu/ZKwJMk5haD25DEnenBYL++Cl3+sNGYxOGS42QlmYj6Mrq1LPw== +xterm@5.3.0-beta.58: + version "5.3.0-beta.58" + resolved "https://registry.yarnpkg.com/xterm/-/xterm-5.3.0-beta.58.tgz#4bae06639c90952b270e4714938c151ce339b5f0" + integrity sha512-EIOgp+7aqCToI0XjDqORXAe2lJS/XSZXWPzCpyTDmF+DJ56gyw+913gdPoIEWOw3mRylrJtEyIpFcdW7CDA6rQ== yallist@^4.0.0: version "4.0.0" diff --git a/yarn.lock b/yarn.lock index b2b8a437cc0..96c77bcd45a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10759,45 +10759,45 @@ xtend@~2.1.1: dependencies: object-keys "~0.4.0" -xterm-addon-canvas@0.5.0-beta.9: - version "0.5.0-beta.9" - resolved "https://registry.yarnpkg.com/xterm-addon-canvas/-/xterm-addon-canvas-0.5.0-beta.9.tgz#d4a9536cf586f78a54527751e03abf6445613886" - integrity sha512-AMyFctHbIWx0aLcACINuZqFFNoz4ndGtIAb4pQguIl9t8r+2otiV11MY4FJmPM0kUzEzoLWzVFJaGxOzykCWuw== +xterm-addon-canvas@0.5.0-beta.19: + version "0.5.0-beta.19" + resolved "https://registry.yarnpkg.com/xterm-addon-canvas/-/xterm-addon-canvas-0.5.0-beta.19.tgz#a2b67554191fae29c901c4a4b398fc28dc345afe" + integrity sha512-eF6b7SBZslmwqCLiWTGnjna4bdjd28cQ+ivZH8SVjE5xP3JGAHGWs/fZm5E3eR6pcHEOkX++/FxByuvhOVXIXQ== -xterm-addon-image@0.6.0-beta.2: - version "0.6.0-beta.2" - resolved "https://registry.yarnpkg.com/xterm-addon-image/-/xterm-addon-image-0.6.0-beta.2.tgz#04c5ea11c89032b01b577b37f891109168ed0b09" - integrity sha512-58d1mqIpJwq8Zy/a/QM8JVuA1g5SceG8UvLoj9T6r+2XIktka6GK2oS66Fmo+0MP0s0HDPy+yJtl8lHY6UyzHw== +xterm-addon-image@0.6.0-beta.11: + version "0.6.0-beta.11" + resolved "https://registry.yarnpkg.com/xterm-addon-image/-/xterm-addon-image-0.6.0-beta.11.tgz#17dffc5f38480a4fac231649ef6e313a8f46d614" + integrity sha512-KPsqJo8sSAawO4ze7xvjtS5evbPtlscy16NiSAteh/1AgOffmTnVhJTs3W84dnks2b13FaMEI/WOiCDIJjDV3A== -xterm-addon-search@0.13.0-beta.8: - version "0.13.0-beta.8" - resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.13.0-beta.8.tgz#90bc70bff87cd7e4f540cce51d9f968f04d5c0ef" - integrity sha512-Hlocg6gGvKAs4eRTW78wTtVqaOEurweJjdyPDjr7KrzwlEEsASsUXJaB2+vgsyTFKuYnCuLrp5u369jck993GQ== +xterm-addon-search@0.13.0-beta.17: + version "0.13.0-beta.17" + resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.13.0-beta.17.tgz#5379cf3085370c55241d99e95b008c0cbf4e6e53" + integrity sha512-0OKwV9isk4OXHLlhRE8Ohqnmpcd0ExWKtorjeaFxqm4f6xc30qZcJTs0hSMzVZ83foedPJcd6hH0hW2pnxOz3Q== -xterm-addon-serialize@0.11.0-beta.8: - version "0.11.0-beta.8" - resolved "https://registry.yarnpkg.com/xterm-addon-serialize/-/xterm-addon-serialize-0.11.0-beta.8.tgz#343357aad7c549a37aacac2fb19692b1c2fd69cd" - integrity sha512-1jNrX+Y8dorWtjMvz02mRUP+ahqQ4STO0lYlKe8m06p+NYuFk24CylnPZFuBgk91OUU3RAdl4glaKh5M4f0/Zw== +xterm-addon-serialize@0.11.0-beta.17: + version "0.11.0-beta.17" + resolved "https://registry.yarnpkg.com/xterm-addon-serialize/-/xterm-addon-serialize-0.11.0-beta.17.tgz#170738ab615e2974c593d41531d41c02b8af1da7" + integrity sha512-zNsUQfIbRD8fL0gHGJJ14DXL22Kduv6pR+QnISReoQqhEEsWANPKpOduJLce7B4y+BJuiOGkT7R7qbMKbj9Ecw== -xterm-addon-unicode11@0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/xterm-addon-unicode11/-/xterm-addon-unicode11-0.5.0.tgz#41c0d96acc1e3bb6c6596eee64e163b6bca74be7" - integrity sha512-Jm4/g4QiTxiKiTbYICQgC791ubhIZyoIwxAIgOW8z8HWFNY+lwk+dwaKEaEeGBfM48Vk8fklsUW9u/PlenYEBg== +xterm-addon-unicode11@0.6.0-beta.9: + version "0.6.0-beta.9" + resolved "https://registry.yarnpkg.com/xterm-addon-unicode11/-/xterm-addon-unicode11-0.6.0-beta.9.tgz#1f476f77cf8c8e4e7ca1a1421b85ac45405db679" + integrity sha512-DH9OIH0EakIdCnzZcIH7NLgUqXwa8WT9fqmi+2CWzt4NN1AH5kSE/3Vk+/uurE5upxDloKw6dtLH9XHpfULV6g== -xterm-addon-webgl@0.16.0-beta.16: - version "0.16.0-beta.16" - resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.16.0-beta.16.tgz#2c31308f8c7f636576720adca529297f8fff3224" - integrity sha512-k0ZSwpBVtxXaqUc29CmlfFgIK7LEYAmwcDC3QVp2ESZo2JHYuQrWFpImjbzbYu0ON6qqcfbX8SnbzRid/XfGUg== +xterm-addon-webgl@0.16.0-beta.27: + version "0.16.0-beta.27" + resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.16.0-beta.27.tgz#f4133a40044f0b6448ea87152abf6c9009729100" + integrity sha512-YiwCvTvgfcNGtQdpzcgxKINE6mG63cPfDxfoxCAbodNGYF66k9VzhIXNdCQtVtu+s6+pEc9YequENe78SSZloA== -xterm-headless@5.3.0-beta.46: - version "5.3.0-beta.46" - resolved "https://registry.yarnpkg.com/xterm-headless/-/xterm-headless-5.3.0-beta.46.tgz#3f941f673e3c61aad2705e4b34b42fbe467aed48" - integrity sha512-e/VbZKrfyD1TTxOY5/jah3dUih6q8nTO5v5GQV7YOASp+yyI0XHKiDjLrCyFPQOLTKxCcRutMHvr+CoCcPpcHg== +xterm-headless@5.3.0-beta.58: + version "5.3.0-beta.58" + resolved "https://registry.yarnpkg.com/xterm-headless/-/xterm-headless-5.3.0-beta.58.tgz#e6a3dbfafdb28435130ce3925ac3194c0ee2c281" + integrity sha512-ekzr3LX8p26qHDyVRs3lys08veHFv9wGOKaHd49kMgktICHsikJ48HNJq5Twp3ZnXyqlIP9CV34BZJ1SBfWmtQ== -xterm@5.3.0-beta.46: - version "5.3.0-beta.46" - resolved "https://registry.yarnpkg.com/xterm/-/xterm-5.3.0-beta.46.tgz#9bd2b2a588c88ae64f1989ca3bf5bd9116554b5a" - integrity sha512-keB3C6sXm56ug1+hylAQiNyZP4YtPgd2W+Gu/ZKwJMk5haD25DEnenBYL++Cl3+sNGYxOGS42QlmYj6Mrq1LPw== +xterm@5.3.0-beta.58: + version "5.3.0-beta.58" + resolved "https://registry.yarnpkg.com/xterm/-/xterm-5.3.0-beta.58.tgz#4bae06639c90952b270e4714938c151ce339b5f0" + integrity sha512-EIOgp+7aqCToI0XjDqORXAe2lJS/XSZXWPzCpyTDmF+DJ56gyw+913gdPoIEWOw3mRylrJtEyIpFcdW7CDA6rQ== y18n@^3.2.1: version "3.2.2" From c8219ae7685f9fe9a6d0a2a7e23bba1591ccf4d2 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Tue, 22 Aug 2023 07:55:06 -0700 Subject: [PATCH 079/221] Change applyAtProcessCreation behavior Part of #179476 --- .../api/common/extHostTerminalService.ts | 15 +++++++++------ .../vscode.proposed.envCollectionOptions.d.ts | 15 +++++++-------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/src/vs/workbench/api/common/extHostTerminalService.ts b/src/vs/workbench/api/common/extHostTerminalService.ts index d91e8fe990f..371eace01f7 100644 --- a/src/vs/workbench/api/common/extHostTerminalService.ts +++ b/src/vs/workbench/api/common/extHostTerminalService.ts @@ -965,22 +965,25 @@ class UnifiedEnvironmentVariableCollection { } const key = this.getKey(variable, mutator.scope); const current = this.map.get(key); + const newOptions = mutator.options ? { + applyAtProcessCreation: mutator.options.applyAtProcessCreation ?? false, + applyAtShellIntegration: mutator.options.applyAtShellIntegration ?? false, + } : { + applyAtProcessCreation: true + }; if ( !current || current.value !== mutator.value || current.type !== mutator.type || - current.options?.applyAtProcessCreation !== (mutator.options.applyAtProcessCreation ?? true) || - current.options?.applyAtShellIntegration !== (mutator.options.applyAtShellIntegration ?? false) || + current.options?.applyAtProcessCreation !== newOptions.applyAtProcessCreation || + current.options?.applyAtShellIntegration !== newOptions.applyAtShellIntegration || current.scope?.workspaceFolder?.index !== mutator.scope?.workspaceFolder?.index ) { const key = this.getKey(variable, mutator.scope); const value: IEnvironmentVariableMutator = { variable, ...mutator, - options: { - applyAtProcessCreation: mutator.options.applyAtProcessCreation ?? true, - applyAtShellIntegration: mutator.options.applyAtShellIntegration ?? false, - } + options: newOptions }; this.map.set(key, value); this._onDidChangeCollection.fire(); diff --git a/src/vscode-dts/vscode.proposed.envCollectionOptions.d.ts b/src/vscode-dts/vscode.proposed.envCollectionOptions.d.ts index d25a92725a4..9a854922a2d 100644 --- a/src/vscode-dts/vscode.proposed.envCollectionOptions.d.ts +++ b/src/vscode-dts/vscode.proposed.envCollectionOptions.d.ts @@ -13,16 +13,12 @@ declare module 'vscode' { export interface EnvironmentVariableMutatorOptions { /** * Apply to the environment just before the process is created. - * - * Defaults to true. */ applyAtProcessCreation?: boolean; /** * Apply to the environment in the shell integration script. Note that this _will not_ apply * the mutator if shell integration is disabled or not working for some reason. - * - * Defaults to false. */ applyAtShellIntegration?: boolean; } @@ -32,24 +28,27 @@ declare module 'vscode' { */ export interface EnvironmentVariableMutator { /** - * Options applied to the mutator. + * Options applied to the mutator */ readonly options: EnvironmentVariableMutatorOptions; } export interface EnvironmentVariableCollection extends Iterable<[variable: string, mutator: EnvironmentVariableMutator]> { /** - * @param options Options applied to the mutator. + * @param options Options applied to the mutator, when not options are provided this will + * default to `{ applyAtProcessCreation: true }` */ replace(variable: string, value: string, options?: EnvironmentVariableMutatorOptions): void; /** - * @param options Options applied to the mutator. + * @param options Options applied to the mutator, when not options are provided this will + * default to `{ applyAtProcessCreation: true }` */ append(variable: string, value: string, options?: EnvironmentVariableMutatorOptions): void; /** - * @param options Options applied to the mutator. + * @param options Options applied to the mutator, when not options are provided this will + * default to `{ applyAtProcessCreation: true }` */ prepend(variable: string, value: string, options?: EnvironmentVariableMutatorOptions): void; } From 4f8b2ecbee391337d93bf2fdfe17a48945e1a107 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Tue, 22 Aug 2023 07:56:09 -0700 Subject: [PATCH 080/221] Fix typo --- src/vscode-dts/vscode.proposed.envCollectionOptions.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vscode-dts/vscode.proposed.envCollectionOptions.d.ts b/src/vscode-dts/vscode.proposed.envCollectionOptions.d.ts index 9a854922a2d..1de5bed146e 100644 --- a/src/vscode-dts/vscode.proposed.envCollectionOptions.d.ts +++ b/src/vscode-dts/vscode.proposed.envCollectionOptions.d.ts @@ -28,7 +28,7 @@ declare module 'vscode' { */ export interface EnvironmentVariableMutator { /** - * Options applied to the mutator + * Options applied to the mutator. */ readonly options: EnvironmentVariableMutatorOptions; } From be2c1b6c06e90dc6b66d1abe513a8c2dbf5ffc26 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Tue, 22 Aug 2023 08:21:32 -0700 Subject: [PATCH 081/221] Pass in correct options --- src/vs/workbench/api/common/extHostTerminalService.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/api/common/extHostTerminalService.ts b/src/vs/workbench/api/common/extHostTerminalService.ts index 371eace01f7..01ad5427b7c 100644 --- a/src/vs/workbench/api/common/extHostTerminalService.ts +++ b/src/vs/workbench/api/common/extHostTerminalService.ts @@ -942,21 +942,21 @@ class UnifiedEnvironmentVariableCollection { if (this._extension && options) { checkProposedApiEnabled(this._extension, 'envCollectionOptions'); } - this._setIfDiffers(variable, { value, type: EnvironmentVariableMutatorType.Replace, options: options ?? {}, scope }); + this._setIfDiffers(variable, { value, type: EnvironmentVariableMutatorType.Replace, options: options ?? { applyAtProcessCreation: true }, scope }); } append(variable: string, value: string, options: vscode.EnvironmentVariableMutatorOptions | undefined, scope: vscode.EnvironmentVariableScope | undefined): void { if (this._extension && options) { checkProposedApiEnabled(this._extension, 'envCollectionOptions'); } - this._setIfDiffers(variable, { value, type: EnvironmentVariableMutatorType.Append, options: options ?? {}, scope }); + this._setIfDiffers(variable, { value, type: EnvironmentVariableMutatorType.Append, options: options ?? { applyAtProcessCreation: true }, scope }); } prepend(variable: string, value: string, options: vscode.EnvironmentVariableMutatorOptions | undefined, scope: vscode.EnvironmentVariableScope | undefined): void { if (this._extension && options) { checkProposedApiEnabled(this._extension, 'envCollectionOptions'); } - this._setIfDiffers(variable, { value, type: EnvironmentVariableMutatorType.Prepend, options: options ?? {}, scope }); + this._setIfDiffers(variable, { value, type: EnvironmentVariableMutatorType.Prepend, options: options ?? { applyAtProcessCreation: true }, scope }); } private _setIfDiffers(variable: string, mutator: vscode.EnvironmentVariableMutator & { scope: vscode.EnvironmentVariableScope | undefined }): void { From bdda40632a4d850a6411850e5d0a7cf03a840186 Mon Sep 17 00:00:00 2001 From: David Dossett Date: Tue, 22 Aug 2023 09:12:18 -0700 Subject: [PATCH 082/221] Tweak slash command styling..again (#190290) --- .../contrib/chat/browser/chatSlashCommandContentWidget.css | 4 ++-- src/vs/workbench/contrib/chat/browser/media/chat.css | 5 +++-- src/vs/workbench/contrib/inlineChat/browser/inlineChat.css | 2 +- .../workbench/contrib/inlineChat/browser/inlineChatWidget.ts | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/contrib/chat/browser/chatSlashCommandContentWidget.css b/src/vs/workbench/contrib/chat/browser/chatSlashCommandContentWidget.css index 6f78c0edda9..d2568dbbfed 100644 --- a/src/vs/workbench/contrib/chat/browser/chatSlashCommandContentWidget.css +++ b/src/vs/workbench/contrib/chat/browser/chatSlashCommandContentWidget.css @@ -4,8 +4,8 @@ *--------------------------------------------------------------------------------------------*/ .chat-slash-command-content-widget { - padding: 1px 3px; - border-radius: 3px; background-color: var(--vscode-chat-slashCommandBackground); color: var(--vscode-chat-slashCommandForeground); + border-radius: 3px; + padding: 1px; } diff --git a/src/vs/workbench/contrib/chat/browser/media/chat.css b/src/vs/workbench/contrib/chat/browser/media/chat.css index 7e193499146..a5275042f81 100644 --- a/src/vs/workbench/contrib/chat/browser/media/chat.css +++ b/src/vs/workbench/contrib/chat/browser/media/chat.css @@ -228,9 +228,10 @@ margin: 0px 20px; background-color: var(--vscode-input-background); border: 1px solid var(--vscode-input-border, transparent); - border-radius: 2px; + border-radius: 4px; position: relative; - padding: 0 4px; + padding: 0 6px; + margin-bottom: 4px; align-items: center; justify-content: space-between; } diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChat.css b/src/vs/workbench/contrib/inlineChat/browser/inlineChat.css index 457fd102c76..fe2e0ccde7a 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChat.css +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChat.css @@ -42,7 +42,7 @@ display: flex; align-items: center; justify-content: space-between; - padding: 2px 2px 2px 4px; + padding: 2px 2px 2px 6px; background-color: var(--vscode-inlineChatInput-background); cursor: text; } diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts index bf16c0aec05..31d9fa9c36b 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts @@ -756,7 +756,7 @@ export class InlineChatWidget { this._slashCommandContentWidget.show(); // inject detail when otherwise empty - if (firstLine === `/${command.command} `) { + if (firstLine === `/${command.command}`) { newDecorations.push({ range: new Range(1, withSlash.length + 1, 1, withSlash.length + 2), options: { From e5a07457e479387985a04705c6d374e83ae90375 Mon Sep 17 00:00:00 2001 From: Henning Dieterichs Date: Tue, 22 Aug 2023 15:27:59 +0200 Subject: [PATCH 083/221] Improves moved code arrow rendering. --- .../lib/stylelint/vscode-known-variables.json | 3 +- src/vs/base/common/arrays.ts | 17 ++ .../widget/diffEditorWidget2/colors.ts | 6 + .../diffEditorDecorations.ts | 63 +++--- .../diffEditorWidget2/diffEditorViewModel.ts | 4 +- .../diffEditorWidget2.contribution.ts | 7 +- .../diffEditorWidget2/diffEditorWidget2.ts | 24 ++- .../widget/diffEditorWidget2/lineAlignment.ts | 4 +- .../diffEditorWidget2/movedBlocksLines.ts | 189 +++++++++++++----- .../widget/diffEditorWidget2/style.css | 20 ++ src/vs/editor/common/core/lineRange.ts | 4 + src/vs/editor/common/core/offsetRange.ts | 58 ++++++ src/vs/monaco.d.ts | 1 + 13 files changed, 297 insertions(+), 103 deletions(-) diff --git a/build/lib/stylelint/vscode-known-variables.json b/build/lib/stylelint/vscode-known-variables.json index 73faa4aaa12..a7d22a17b85 100644 --- a/build/lib/stylelint/vscode-known-variables.json +++ b/build/lib/stylelint/vscode-known-variables.json @@ -99,6 +99,7 @@ "--vscode-diffEditor-insertedTextBackground", "--vscode-diffEditor-insertedTextBorder", "--vscode-diffEditor-move-border", + "--vscode-diffEditor-moveActive-border", "--vscode-diffEditor-removedLineBackground", "--vscode-diffEditor-removedTextBackground", "--vscode-diffEditor-removedTextBorder", @@ -778,4 +779,4 @@ "--z-index-notebook-sticky-scroll", "--zoom-factor" ] -} +} \ No newline at end of file diff --git a/src/vs/base/common/arrays.ts b/src/vs/base/common/arrays.ts index a54c2c59f9c..22c2859f5e9 100644 --- a/src/vs/base/common/arrays.ts +++ b/src/vs/base/common/arrays.ts @@ -707,6 +707,8 @@ export function tieBreakComparators(...comparators: Comparator[]): */ export const numberComparator: Comparator = (a, b) => a - b; +export const booleanComparator: Comparator = (a, b) => numberComparator(a ? 1 : 0, b ? 1 : 0); + export function reverseOrder(comparator: Comparator): Comparator { return (a, b) => -comparator(a, b); } @@ -754,6 +756,21 @@ export function findMinBy(items: readonly T[], comparator: Comparator): T return findMaxBy(items, (a, b) => -comparator(a, b)); } +export function findMaxIdxBy(items: readonly T[], comparator: Comparator): number { + if (items.length === 0) { + return -1; + } + + let maxIdx = 0; + for (let i = 1; i < items.length; i++) { + const item = items[i]; + if (comparator(item, items[maxIdx]) > 0) { + maxIdx = i; + } + } + return maxIdx; +} + export class ArrayQueue { private firstIdx = 0; private lastIdx = this.items.length - 1; diff --git a/src/vs/editor/browser/widget/diffEditorWidget2/colors.ts b/src/vs/editor/browser/widget/diffEditorWidget2/colors.ts index 8c78445d74b..449e67f06f8 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget2/colors.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget2/colors.ts @@ -11,3 +11,9 @@ export const diffMoveBorder = registerColor( { dark: '#8b8b8b9c', light: '#8b8b8b9c', hcDark: '#8b8b8b9c', hcLight: '#8b8b8b9c', }, localize('diffEditor.move.border', 'The border color for text that got moved in the diff editor.') ); + +export const diffMoveBorderActive = registerColor( + 'diffEditor.moveActive.border', + { dark: '#FFA500', light: '#FFA500', hcDark: '#FFA500', hcLight: '#FFA500', }, + localize('diffEditor.moveActive.border', 'The active border color for text that got moved in the diff editor.') +); diff --git a/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorDecorations.ts b/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorDecorations.ts index 5d9af4098f9..194f37c9882 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorDecorations.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorDecorations.ts @@ -5,14 +5,12 @@ import { Disposable } from 'vs/base/common/lifecycle'; import { IObservable, derived } from 'vs/base/common/observable'; -import { isDefined } from 'vs/base/common/types'; import { arrowRevertChange, diffAddDecoration, diffAddDecorationEmpty, diffDeleteDecoration, diffDeleteDecorationEmpty, diffLineAddDecorationBackground, diffLineAddDecorationBackgroundWithIndicator, diffLineDeleteDecorationBackground, diffLineDeleteDecorationBackgroundWithIndicator, diffWholeLineAddDecoration, diffWholeLineDeleteDecoration } from 'vs/editor/browser/widget/diffEditorWidget2/decorations'; import { DiffEditorEditors } from 'vs/editor/browser/widget/diffEditorWidget2/diffEditorEditors'; import { DiffEditorOptions } from 'vs/editor/browser/widget/diffEditorWidget2/diffEditorOptions'; import { DiffEditorViewModel } from 'vs/editor/browser/widget/diffEditorWidget2/diffEditorViewModel'; import { MovedBlocksLinesPart } from 'vs/editor/browser/widget/diffEditorWidget2/movedBlocksLines'; import { applyObservableDecorations } from 'vs/editor/browser/widget/diffEditorWidget2/utils'; -import { LineRange } from 'vs/editor/common/core/lineRange'; import { Position } from 'vs/editor/common/core/position'; import { Range } from 'vs/editor/common/core/range'; import { IModelDeltaDecoration } from 'vs/editor/common/model'; @@ -42,46 +40,37 @@ export class DiffEditorDecorations extends Disposable { const originalDecorations: IModelDeltaDecoration[] = []; const modifiedDecorations: IModelDeltaDecoration[] = []; - for (const m of diff.mappings) { - const fullRangeOriginal = LineRange.subtract(m.lineRangeMapping.originalRange, currentMove?.lineRangeMapping.original) - .map(i => i.toInclusiveRange()).filter(isDefined); - for (const range of fullRangeOriginal) { - originalDecorations.push({ range, options: renderIndicators ? diffLineDeleteDecorationBackgroundWithIndicator : diffLineDeleteDecorationBackground }); - } - - const fullRangeModified = LineRange.subtract(m.lineRangeMapping.modifiedRange, currentMove?.lineRangeMapping.modified) - .map(i => i.toInclusiveRange()).filter(isDefined); - for (const range of fullRangeModified) { - modifiedDecorations.push({ range, options: renderIndicators ? diffLineAddDecorationBackgroundWithIndicator : diffLineAddDecorationBackground }); - } - - if (m.lineRangeMapping.modifiedRange.isEmpty || m.lineRangeMapping.originalRange.isEmpty) { - for (const range of fullRangeOriginal) { - originalDecorations.push({ range, options: diffWholeLineDeleteDecoration }); + if (!currentMove) { + for (const m of diff.mappings) { + if (!m.lineRangeMapping.originalRange.isEmpty) { + originalDecorations.push({ range: m.lineRangeMapping.originalRange.toInclusiveRange()!, options: renderIndicators ? diffLineDeleteDecorationBackgroundWithIndicator : diffLineDeleteDecorationBackground }); } - for (const range of fullRangeModified) { - modifiedDecorations.push({ range, options: diffWholeLineAddDecoration }); + if (!m.lineRangeMapping.modifiedRange.isEmpty) { + modifiedDecorations.push({ range: m.lineRangeMapping.modifiedRange.toInclusiveRange()!, options: renderIndicators ? diffLineAddDecorationBackgroundWithIndicator : diffLineAddDecorationBackground }); } - } else { - for (const i of m.lineRangeMapping.innerChanges || []) { - if (currentMove - && (currentMove.lineRangeMapping.original.intersect(new LineRange(i.originalRange.startLineNumber, i.originalRange.endLineNumber)) - || currentMove.lineRangeMapping.modified.intersect(new LineRange(i.modifiedRange.startLineNumber, i.modifiedRange.endLineNumber)))) { - continue; - } - // Don't show empty markers outside the line range - if (m.lineRangeMapping.originalRange.contains(i.originalRange.startLineNumber)) { - originalDecorations.push({ range: i.originalRange, options: (i.originalRange.isEmpty() && showEmptyDecorations) ? diffDeleteDecorationEmpty : diffDeleteDecoration }); + if (m.lineRangeMapping.modifiedRange.isEmpty || m.lineRangeMapping.originalRange.isEmpty) { + if (!m.lineRangeMapping.originalRange.isEmpty) { + originalDecorations.push({ range: m.lineRangeMapping.originalRange.toInclusiveRange()!, options: diffWholeLineDeleteDecoration }); } - if (m.lineRangeMapping.modifiedRange.contains(i.modifiedRange.startLineNumber)) { - modifiedDecorations.push({ range: i.modifiedRange, options: (i.modifiedRange.isEmpty() && showEmptyDecorations) ? diffAddDecorationEmpty : diffAddDecoration }); + if (!m.lineRangeMapping.modifiedRange.isEmpty) { + modifiedDecorations.push({ range: m.lineRangeMapping.modifiedRange.toInclusiveRange()!, options: diffWholeLineAddDecoration }); + } + } else { + for (const i of m.lineRangeMapping.innerChanges || []) { + // Don't show empty markers outside the line range + if (m.lineRangeMapping.originalRange.contains(i.originalRange.startLineNumber)) { + originalDecorations.push({ range: i.originalRange, options: (i.originalRange.isEmpty() && showEmptyDecorations) ? diffDeleteDecorationEmpty : diffDeleteDecoration }); + } + if (m.lineRangeMapping.modifiedRange.contains(i.modifiedRange.startLineNumber)) { + modifiedDecorations.push({ range: i.modifiedRange, options: (i.modifiedRange.isEmpty() && showEmptyDecorations) ? diffAddDecorationEmpty : diffAddDecoration }); + } } } - } - if (!m.lineRangeMapping.modifiedRange.isEmpty && this._options.shouldRenderRevertArrows.read(reader) && !currentMove) { - modifiedDecorations.push({ range: Range.fromPositions(new Position(m.lineRangeMapping.modifiedRange.startLineNumber, 1)), options: arrowRevertChange }); + if (!m.lineRangeMapping.modifiedRange.isEmpty && this._options.shouldRenderRevertArrows.read(reader) && !currentMove) { + modifiedDecorations.push({ range: Range.fromPositions(new Position(m.lineRangeMapping.modifiedRange.startLineNumber, 1)), options: arrowRevertChange }); + } } } @@ -107,7 +96,7 @@ export class DiffEditorDecorations extends Disposable { originalDecorations.push({ range: m.lineRangeMapping.original.toInclusiveRange()!, options: { description: 'moved', - blockClassName: 'movedOriginal', + blockClassName: 'movedOriginal' + (m === currentMove ? ' currentMove' : ''), blockPadding: [MovedBlocksLinesPart.movedCodeBlockPadding, 0, MovedBlocksLinesPart.movedCodeBlockPadding, MovedBlocksLinesPart.movedCodeBlockPadding], } }); @@ -115,7 +104,7 @@ export class DiffEditorDecorations extends Disposable { modifiedDecorations.push({ range: m.lineRangeMapping.modified.toInclusiveRange()!, options: { description: 'moved', - blockClassName: 'movedModified', + blockClassName: 'movedModified' + (m === currentMove ? ' currentMove' : ''), blockPadding: [4, 0, 4, 4], } }); diff --git a/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorViewModel.ts b/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorViewModel.ts index 448ccb5b27e..4927ebeb9c1 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorViewModel.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorViewModel.ts @@ -11,13 +11,14 @@ import { ISerializedLineRange, LineRange } from 'vs/editor/common/core/lineRange import { Range } from 'vs/editor/common/core/range'; import { IDocumentDiff, IDocumentDiffProvider } from 'vs/editor/common/diff/documentDiffProvider'; import { LineRangeMapping, MovedText, RangeMapping, SimpleLineRangeMapping } from 'vs/editor/common/diff/linesDiffComputer'; -import { lineRangeMappingFromRangeMappings } from 'vs/editor/common/diff/standardLinesDiffComputer'; +import { StandardLinesDiffComputer, lineRangeMappingFromRangeMappings } from 'vs/editor/common/diff/standardLinesDiffComputer'; import { IDiffEditorModel, IDiffEditorViewModel } from 'vs/editor/common/editorCommon'; import { ITextModel } from 'vs/editor/common/model'; import { TextEditInfo } from 'vs/editor/common/model/bracketPairsTextModelPart/bracketPairsTree/beforeEditPositionMapper'; import { combineTextEditInfos } from 'vs/editor/common/model/bracketPairsTextModelPart/bracketPairsTree/combineTextEditInfos'; import { lengthAdd, lengthDiffNonNegative, lengthGetLineCount, lengthOfRange, lengthToPosition, lengthZero, positionToLength } from 'vs/editor/common/model/bracketPairsTextModelPart/bracketPairsTree/length'; import { DiffEditorOptions } from './diffEditorOptions'; +import { readHotReloadableExport } from 'vs/editor/browser/widget/diffEditorWidget2/utils'; export class DiffEditorViewModel extends Disposable implements IDiffEditorViewModel { private readonly _isDiffUpToDate = observableValue('isDiffUpToDate', false); @@ -147,6 +148,7 @@ export class DiffEditorViewModel extends Disposable implements IDiffEditorViewMo debouncer.cancel(); contentChangedSignal.read(reader); documentDiffProviderOptionChanged.read(reader); + readHotReloadableExport(StandardLinesDiffComputer, reader); this._isDiffUpToDate.set(false, undefined); diff --git a/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2.contribution.ts b/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2.contribution.ts index d312eb5629a..13c654d867f 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2.contribution.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2.contribution.ts @@ -91,14 +91,10 @@ MenuRegistry.appendMenuItem(MenuId.EditorTitle, { ) }); -/* -TODO@hediet add this back once move detection is more polished. -Users can still enable this via settings.json (config.diffEditor.experimental.showMoves). - MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: new ToggleShowMovedCodeBlocks().desc.id, - title: localize('showMoves', "Show Moves"), + title: localize('showMoves', "Show Moved Code Blocks"), icon: Codicon.move, toggled: ContextKeyEqualsExpr.create('config.diffEditor.experimental.showMoves', true), }, @@ -106,7 +102,6 @@ MenuRegistry.appendMenuItem(MenuId.EditorTitle, { group: '1_diff', when: ContextKeyEqualsExpr.create('diffEditorVersion', 2) }); -*/ const diffEditorCategory: ILocalizedString = { value: localize('diffEditor', 'Diff Editor'), diff --git a/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2.ts b/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2.ts index 21b5f67aaae..63973ae2e03 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2.ts @@ -79,6 +79,8 @@ export class DiffEditorWidget2 extends DelegatingEditor implements IDiffEditor { private readonly _options: DiffEditorOptions; private readonly _editors: DiffEditorEditors; + private readonly movedBlocksLinesPart = observableValue('MovedBlocksLinesPart', undefined); + constructor( private readonly _domElement: HTMLElement, options: Readonly, @@ -204,13 +206,15 @@ export class DiffEditorWidget2 extends DelegatingEditor implements IDiffEditor { this._register(keepAlive(this._layoutInfo, true)); - this._register(new MovedBlocksLinesPart( - this.elements.root, - this._diffModel, - this._layoutInfo.map(i => i.originalEditor), - this._layoutInfo.map(i => i.modifiedEditor), - this._editors, - )); + this._register(autorunWithStore((reader, store) => { + this.movedBlocksLinesPart.set(store.add(new (readHotReloadableExport(MovedBlocksLinesPart, reader))( + this.elements.root, + this._diffModel, + this._layoutInfo.map(i => i.originalEditor), + this._layoutInfo.map(i => i.modifiedEditor), + this._editors, + )), undefined); + })); this._register(applyStyle(this.elements.overlay, { width: this._layoutInfo.map((i, r) => i.originalEditor.width + (this._options.renderSideBySide.read(r) ? 0 : i.modifiedEditor.width)), @@ -285,13 +289,15 @@ export class DiffEditorWidget2 extends DelegatingEditor implements IDiffEditor { const originalWidth = sashLeft ?? Math.max(5, this._editors.original.getLayoutInfo().decorationsLeft); const modifiedWidth = width - originalWidth - (this._options.renderOverviewRuler.read(reader) ? OverviewRulerPart.ENTIRE_DIFF_OVERVIEW_WIDTH : 0); - this.elements.original.style.width = originalWidth + 'px'; + const movedBlocksLinesWidth = this.movedBlocksLinesPart.read(reader)?.width.read(reader) ?? 0; + const originalWidthWithoutMovedBlockLines = originalWidth - movedBlocksLinesWidth; + this.elements.original.style.width = originalWidthWithoutMovedBlockLines + 'px'; this.elements.original.style.left = '0px'; this.elements.modified.style.width = modifiedWidth + 'px'; this.elements.modified.style.left = originalWidth + 'px'; - this._editors.original.layout({ width: originalWidth, height }); + this._editors.original.layout({ width: originalWidthWithoutMovedBlockLines, height }); this._editors.modified.layout({ width: modifiedWidth, height }); return { diff --git a/src/vs/editor/browser/widget/diffEditorWidget2/lineAlignment.ts b/src/vs/editor/browser/widget/diffEditorWidget2/lineAlignment.ts index 92fb780d62c..3a95ce28942 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget2/lineAlignment.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget2/lineAlignment.ts @@ -265,7 +265,7 @@ export class ViewZoneManager extends Disposable { } else { const delta = a.modifiedHeightInPx - a.originalHeightInPx; if (delta > 0) { - if (syncedMovedText?.lineRangeMapping.original.contains(a.originalRange.endLineNumberExclusive - 1)) { + if (syncedMovedText?.lineRangeMapping.original.delta(-1).deltaLength(2).contains(a.originalRange.endLineNumberExclusive - 1)) { continue; } @@ -276,7 +276,7 @@ export class ViewZoneManager extends Disposable { showInHiddenAreas: true, }); } else { - if (syncedMovedText?.lineRangeMapping.modified.contains(a.modifiedRange.endLineNumberExclusive - 1)) { + if (syncedMovedText?.lineRangeMapping.modified.delta(-1).deltaLength(2).contains(a.modifiedRange.endLineNumberExclusive - 1)) { continue; } diff --git a/src/vs/editor/browser/widget/diffEditorWidget2/movedBlocksLines.ts b/src/vs/editor/browser/widget/diffEditorWidget2/movedBlocksLines.ts index b4b628c711f..0763643bf3a 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget2/movedBlocksLines.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget2/movedBlocksLines.ts @@ -3,17 +3,27 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Disposable } from 'vs/base/common/lifecycle'; -import { IObservable, autorun, observableFromEvent, observableSignalFromEvent } from 'vs/base/common/observable'; +import { booleanComparator, compareBy, findMaxIdxBy, findMinBy, numberComparator, tieBreakComparators } from 'vs/base/common/arrays'; +import { Disposable, toDisposable } from 'vs/base/common/lifecycle'; +import { IObservable, autorun, derived, keepAlive, observableFromEvent, observableSignalFromEvent, observableValue } from 'vs/base/common/observable'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { DiffEditorEditors } from 'vs/editor/browser/widget/diffEditorWidget2/diffEditorEditors'; import { DiffEditorViewModel } from 'vs/editor/browser/widget/diffEditorWidget2/diffEditorViewModel'; import { EditorLayoutInfo } from 'vs/editor/common/config/editorOptions'; import { LineRange } from 'vs/editor/common/core/lineRange'; +import { OffsetRange, OffsetRangeSet } from 'vs/editor/common/core/offsetRange'; +import { MovedText } from 'vs/editor/common/diff/linesDiffComputer'; export class MovedBlocksLinesPart extends Disposable { public static readonly movedCodeBlockPadding = 4; + private readonly _element: SVGElement; + private readonly _originalScrollTop = observableFromEvent(this._editors.original.onDidScrollChange, () => this._editors.original.getScrollTop()); + private readonly _modifiedScrollTop = observableFromEvent(this._editors.modified.onDidScrollChange, () => this._editors.modified.getScrollTop()); + private readonly _viewZonesChanged = observableSignalFromEvent('onDidChangeViewZones', this._editors.modified.onDidChangeViewZones); + + public readonly width = observableValue('width', 0); + constructor( private readonly _rootElement: HTMLElement, private readonly _diffModel: IObservable, @@ -23,9 +33,10 @@ export class MovedBlocksLinesPart extends Disposable { ) { super(); - const element = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); - element.setAttribute('class', 'moved-blocks-lines'); - this._rootElement.appendChild(element); + this._element = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); + this._element.setAttribute('class', 'moved-blocks-lines'); + this._rootElement.appendChild(this._element); + this._register(toDisposable(() => this._element.remove())); this._register(autorun(reader => { /** @description update moved blocks lines positioning */ @@ -35,58 +46,142 @@ export class MovedBlocksLinesPart extends Disposable { return; } - element.style.left = `${info.width - info.verticalScrollbarWidth}px`; - element.style.height = `${info.height}px`; - element.style.width = `${info.verticalScrollbarWidth + info.contentLeft - MovedBlocksLinesPart.movedCodeBlockPadding}px`; + this._element.style.left = `${info.width - info.verticalScrollbarWidth}px`; + this._element.style.height = `${info.height}px`; + this._element.style.width = `${info.verticalScrollbarWidth + info.contentLeft - MovedBlocksLinesPart.movedCodeBlockPadding + this.width.read(reader)}px`; })); - const originalScrollTop = observableFromEvent(this._editors.original.onDidScrollChange, () => this._editors.original.getScrollTop()); - const modifiedScrollTop = observableFromEvent(this._editors.modified.onDidScrollChange, () => this._editors.modified.getScrollTop()); - const viewZonesChanged = observableSignalFromEvent('onDidChangeViewZones', this._editors.modified.onDidChangeViewZones); + this._register(keepAlive(this._state, true)); + } - this._register(autorun(reader => { - element.replaceChildren(); + private readonly _state = derived(reader => { + /** @description update moved blocks lines */ - /** @description update moved blocks lines */ - const moves = this._diffModel.read(reader)?.diff.read(reader)?.movedTexts; - if (!moves) { - return; + this._element.replaceChildren(); + const model = this._diffModel.read(reader); + const moves = model?.diff.read(reader)?.movedTexts; + if (!moves || moves.length === 0) { + this.width.set(0, undefined); + return; + } + + this._viewZonesChanged.read(reader); + + const infoOrig = this._originalEditorLayoutInfo.read(reader); + const infoMod = this._modifiedEditorLayoutInfo.read(reader); + if (!infoOrig || !infoMod) { + this.width.set(0, undefined); + return; + } + + const lines = moves.map((move) => { + function computeLineStart(range: LineRange, editor: ICodeEditor) { + const t1 = editor.getTopForLineNumber(range.startLineNumber); + const t2 = editor.getTopForLineNumber(range.endLineNumberExclusive); + return (t1 + t2) / 2; } - viewZonesChanged.read(reader); + const start = computeLineStart(move.lineRangeMapping.original, this._editors.original); + const startOffset = this._originalScrollTop.read(reader); + const end = computeLineStart(move.lineRangeMapping.modified, this._editors.modified); + const endOffset = this._modifiedScrollTop.read(reader); - const info = this._originalEditorLayoutInfo.read(reader); - const info2 = this._modifiedEditorLayoutInfo.read(reader); - if (!info || !info2) { - return; + const from = start - startOffset; + const to = end - endOffset; + + const top = Math.min(start, end); + const bottom = Math.max(start, end); + + return { range: new OffsetRange(top, bottom), from, to, fromWithoutScroll: start, toWithoutScroll: end, move }; + }); + + lines.sort(tieBreakComparators( + compareBy(l => l.fromWithoutScroll > l.toWithoutScroll, booleanComparator), + compareBy(l => -l.fromWithoutScroll, numberComparator) + )); + + const layout = LinesLayout.compute(lines.map(l => l.range)); + + const padding = 10; + const lineAreaLeft = infoOrig.verticalScrollbarWidth; + const lineAreaWidth = (layout.getTrackCount() - 1) * 10 + padding * 2; + const width = lineAreaLeft + lineAreaWidth + (infoMod.contentLeft - MovedBlocksLinesPart.movedCodeBlockPadding); + + let idx = 0; + for (const line of lines) { + const track = layout.getTrack(idx); + const verticalY = lineAreaLeft + padding + track * 10; + + const arrowHeight = 15; + const arrowWidth = 15; + const right = width; + + const rectWidth = infoMod.glyphMarginWidth + infoMod.lineNumbersWidth; + const rectHeight = 18; + const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect'); + rect.classList.add('arrow-rectangle'); + rect.setAttribute('x', `${right - rectWidth}`); + rect.setAttribute('y', `${line.to - rectHeight / 2}`); + rect.setAttribute('width', `${rectWidth}`); + rect.setAttribute('height', `${rectHeight}`); + this._element.appendChild(rect); + + const path = document.createElementNS('http://www.w3.org/2000/svg', 'path'); + if (line.move === model.syncedMovedTexts.read(reader)) { + path.classList.add('currentMove'); } - const width = info.verticalScrollbarWidth + info.contentLeft - MovedBlocksLinesPart.movedCodeBlockPadding; + path.setAttribute('d', `M ${0} ${line.from} L ${verticalY} ${line.from} L ${verticalY} ${line.to} L ${right - arrowWidth} ${line.to}`); + path.setAttribute('fill', 'none'); + this._element.appendChild(path); - let idx = 0; - for (const m of moves) { - function computeLineStart(range: LineRange, editor: ICodeEditor) { - const t1 = editor.getTopForLineNumber(range.startLineNumber); - const t2 = editor.getTopForLineNumber(range.endLineNumberExclusive); - return (t1 + t2) / 2; + const arrowRight = document.createElementNS('http://www.w3.org/2000/svg', 'polygon'); + arrowRight.classList.add('arrow'); + if (line.move === model.syncedMovedTexts.read(reader)) { + arrowRight.classList.add('currentMove'); + } + arrowRight.setAttribute('points', `${right - arrowWidth},${line.to - arrowHeight / 2} ${right},${line.to} ${right - arrowWidth},${line.to + arrowHeight / 2}`); + this._element.appendChild(arrowRight); + + idx++; + } + + this.width.set(lineAreaWidth, undefined); + }); +} + +class LinesLayout { + public static compute(lines: OffsetRange[]): LinesLayout { + const setsPerTrack: OffsetRangeSet[] = []; + const trackPerLineIdx: number[] = []; + + for (const line of lines) { + let trackIdx = setsPerTrack.findIndex(set => !set.intersectsStrict(line)); + if (trackIdx === -1) { + const maxTrackCount = 6; + if (setsPerTrack.length >= maxTrackCount) { + trackIdx = findMaxIdxBy(setsPerTrack, compareBy(set => set.intersectWithRangeLength(line), numberComparator)); + } else { + trackIdx = setsPerTrack.length; + setsPerTrack.push(new OffsetRangeSet()); } - - const start = computeLineStart(m.lineRangeMapping.original, this._editors.original); - const startOffset = originalScrollTop.read(reader); - const end = computeLineStart(m.lineRangeMapping.modified, this._editors.modified); - const endOffset = modifiedScrollTop.read(reader); - - const top = start - startOffset; - const bottom = end - endOffset; - - const center = (width / 2) - moves.length * 5 + idx * 10; - idx++; - - const path = document.createElementNS('http://www.w3.org/2000/svg', 'path'); - path.setAttribute('d', `M ${0} ${top} L ${center} ${top} L ${center} ${bottom} L ${width} ${bottom}`); - - path.setAttribute('fill', 'none'); - element.appendChild(path); } - })); + setsPerTrack[trackIdx].addRange(line); + trackPerLineIdx.push(trackIdx); + } + + return new LinesLayout(setsPerTrack.length, trackPerLineIdx); + } + + private constructor( + private readonly _trackCount: number, + private readonly trackPerLineIdx: number[] + ) { } + + getTrack(lineIdx: number): number { + return this.trackPerLineIdx[lineIdx]; + } + + getTrackCount(): number { + return this._trackCount; } } diff --git a/src/vs/editor/browser/widget/diffEditorWidget2/style.css b/src/vs/editor/browser/widget/diffEditorWidget2/style.css index f8243853b70..8fd6377362f 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget2/style.css +++ b/src/vs/editor/browser/widget/diffEditorWidget2/style.css @@ -78,6 +78,26 @@ border: 2px solid var(--vscode-diffEditor-move-border); } +.monaco-editor .movedOriginal.currentMove, .monaco-editor .movedModified.currentMove { + border: 2px solid var(--vscode-diffEditor-moveActive-border); +} + +.monaco-diff-editor .moved-blocks-lines path.currentMove { + stroke: var(--vscode-diffEditor-moveActive-border); +} + +.monaco-diff-editor .moved-blocks-lines .arrow { + fill: var(--vscode-diffEditor-move-border); +} + +.monaco-diff-editor .moved-blocks-lines .arrow.currentMove { + fill: var(--vscode-diffEditor-moveActive-border); +} + +.monaco-diff-editor .moved-blocks-lines .arrow-rectangle { + fill: var(--vscode-editor-background); +} + .monaco-diff-editor .moved-blocks-lines { position: absolute; pointer-events: none; diff --git a/src/vs/editor/common/core/lineRange.ts b/src/vs/editor/common/core/lineRange.ts index c8779a2881a..568bf03ca2b 100644 --- a/src/vs/editor/common/core/lineRange.ts +++ b/src/vs/editor/common/core/lineRange.ts @@ -154,6 +154,10 @@ export class LineRange { return new LineRange(this.startLineNumber + offset, this.endLineNumberExclusive + offset); } + public deltaLength(offset: number): LineRange { + return new LineRange(this.startLineNumber, this.endLineNumberExclusive + offset); + } + /** * The number of lines this line range spans. */ diff --git a/src/vs/editor/common/core/offsetRange.ts b/src/vs/editor/common/core/offsetRange.ts index 14ff2039fc7..d46cf88a425 100644 --- a/src/vs/editor/common/core/offsetRange.ts +++ b/src/vs/editor/common/core/offsetRange.ts @@ -91,3 +91,61 @@ export class OffsetRange { return undefined; } } + +export class OffsetRangeSet { + private readonly _sortedRanges: OffsetRange[] = []; + + public addRange(range: OffsetRange): void { + let i = 0; + while (i < this._sortedRanges.length && this._sortedRanges[i].endExclusive < range.start) { + i++; + } + let j = i; + while (j < this._sortedRanges.length && this._sortedRanges[j].start <= range.endExclusive) { + j++; + } + if (i === j) { + this._sortedRanges.splice(i, 0, range); + } else { + const start = Math.min(range.start, this._sortedRanges[i].start); + const end = Math.max(range.endExclusive, this._sortedRanges[j - 1].endExclusive); + this._sortedRanges.splice(i, j - i, new OffsetRange(start, end)); + } + } + + public toString(): string { + return this._sortedRanges.map(r => r.toString()).join(', '); + } + + /** + * Returns of there is a value that is contained in this instance and the given range. + */ + public intersectsStrict(other: OffsetRange): boolean { + // TODO use binary search + let i = 0; + while (i < this._sortedRanges.length && this._sortedRanges[i].endExclusive <= other.start) { + i++; + } + return i < this._sortedRanges.length && this._sortedRanges[i].start < other.endExclusive; + } + + public intersectWithRange(other: OffsetRange): OffsetRangeSet { + // TODO use binary search + slice + const result = new OffsetRangeSet(); + for (const range of this._sortedRanges) { + const intersection = range.intersect(other); + if (intersection) { + result.addRange(intersection); + } + } + return result; + } + + public intersectWithRangeLength(other: OffsetRange): number { + return this.intersectWithRange(other).length; + } + + public get length(): number { + return this._sortedRanges.reduce((prev, cur) => prev + cur.length, 0); + } +} diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index 8fbfcd493ae..e6cd4654946 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -2460,6 +2460,7 @@ declare namespace monaco.editor { * Moves this line range by the given offset of line numbers. */ delta(offset: number): LineRange; + deltaLength(offset: number): LineRange; /** * The number of lines this line range spans. */ From 3a26bb70967560f42b94749025cfb26cf7db97c3 Mon Sep 17 00:00:00 2001 From: Henning Dieterichs Date: Tue, 22 Aug 2023 18:01:36 +0200 Subject: [PATCH 084/221] Fixes CI --- .../browser/widget/diffEditorWidget2/movedBlocksLines.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/vs/editor/browser/widget/diffEditorWidget2/movedBlocksLines.ts b/src/vs/editor/browser/widget/diffEditorWidget2/movedBlocksLines.ts index 0763643bf3a..4453cb7ce2d 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget2/movedBlocksLines.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget2/movedBlocksLines.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { booleanComparator, compareBy, findMaxIdxBy, findMinBy, numberComparator, tieBreakComparators } from 'vs/base/common/arrays'; +import { booleanComparator, compareBy, findMaxIdxBy, numberComparator, tieBreakComparators } from 'vs/base/common/arrays'; import { Disposable, toDisposable } from 'vs/base/common/lifecycle'; import { IObservable, autorun, derived, keepAlive, observableFromEvent, observableSignalFromEvent, observableValue } from 'vs/base/common/observable'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; @@ -12,7 +12,6 @@ import { DiffEditorViewModel } from 'vs/editor/browser/widget/diffEditorWidget2/ import { EditorLayoutInfo } from 'vs/editor/common/config/editorOptions'; import { LineRange } from 'vs/editor/common/core/lineRange'; import { OffsetRange, OffsetRangeSet } from 'vs/editor/common/core/offsetRange'; -import { MovedText } from 'vs/editor/common/diff/linesDiffComputer'; export class MovedBlocksLinesPart extends Disposable { public static readonly movedCodeBlockPadding = 4; From 026f38a82cf9c727823d828d9df05e376b441a02 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Tue, 22 Aug 2023 18:44:27 +0200 Subject: [PATCH 085/221] Refactor fix for #188104 (#190977) --- .../common/abstractExtensionManagementService.ts | 14 +++++--------- .../common/extensionManagement.ts | 1 + .../node/extensionManagementService.ts | 2 +- .../browser/gettingStartedService.ts | 5 +++-- .../common/webExtensionManagementService.ts | 2 +- 5 files changed, 11 insertions(+), 13 deletions(-) diff --git a/src/vs/platform/extensionManagement/common/abstractExtensionManagementService.ts b/src/vs/platform/extensionManagement/common/abstractExtensionManagementService.ts index 23f3a635495..829a9b679c9 100644 --- a/src/vs/platform/extensionManagement/common/abstractExtensionManagementService.ts +++ b/src/vs/platform/extensionManagement/common/abstractExtensionManagementService.ts @@ -16,7 +16,7 @@ import * as nls from 'vs/nls'; import { ExtensionManagementError, IExtensionGalleryService, IExtensionIdentifier, IExtensionManagementParticipant, IGalleryExtension, ILocalExtension, InstallOperation, IExtensionsControlManifest, StatisticType, isTargetPlatformCompatible, TargetPlatformToString, ExtensionManagementErrorCode, - InstallOptions, InstallVSIXOptions, UninstallOptions, Metadata, InstallExtensionEvent, DidUninstallExtensionEvent, InstallExtensionResult, UninstallExtensionEvent, IExtensionManagementService, InstallExtensionInfo, EXTENSION_INSTALL_SKIP_WALKTHROUGH_CONTEXT + InstallOptions, InstallVSIXOptions, UninstallOptions, Metadata, InstallExtensionEvent, DidUninstallExtensionEvent, InstallExtensionResult, UninstallExtensionEvent, IExtensionManagementService, InstallExtensionInfo, EXTENSION_INSTALL_DEP_PACK_CONTEXT } from 'vs/platform/extensionManagement/common/extensionManagement'; import { areSameExtensions, ExtensionKey, getGalleryExtensionId, getGalleryExtensionTelemetryData, getLocalExtensionTelemetryData } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; import { ExtensionType, IExtensionManifest, isApplicationScopedExtension, TargetPlatform } from 'vs/platform/extensions/common/extensions'; @@ -35,6 +35,7 @@ export interface IInstallExtensionTask { readonly source: IGalleryExtension | URI; readonly operation: InstallOperation; readonly profileLocation: URI; + readonly options: InstallExtensionTaskOptions; readonly verificationStatus?: ExtensionVerificationStatus; run(): Promise; waitUntilTaskIsFinished(): Promise; @@ -248,7 +249,6 @@ export abstract class AbstractExtensionManagementService extends Disposable impl allInstallExtensionTasks.push({ task: installExtensionTask, manifest }); let installExtensionHasDependents: boolean = false; - const hasPackExtensions = manifest.extensionPack && manifest.extensionPack.length > 0; try { if (installExtensionTaskOptions.donotIncludePackAndDependencies) { this.logService.info('Installing the extension without checking dependencies and pack', installExtensionTask.identifier.id); @@ -256,6 +256,7 @@ export abstract class AbstractExtensionManagementService extends Disposable impl try { const allDepsAndPackExtensionsToInstall = await this.getAllDepsAndPackExtensions(installExtensionTask.identifier, manifest, !!installExtensionTaskOptions.installOnlyNewlyAddedFromExtensionPack, !!installExtensionTaskOptions.installPreReleaseVersion, installExtensionTaskOptions.profileLocation); const installed = await this.getInstalled(undefined, installExtensionTaskOptions.profileLocation); + const options: InstallExtensionTaskOptions = { ...installExtensionTaskOptions, donotIncludePackAndDependencies: true, context: { ...installExtensionTaskOptions.context, [EXTENSION_INSTALL_DEP_PACK_CONTEXT]: true } }; for (const { gallery, manifest } of distinct(allDepsAndPackExtensionsToInstall, ({ gallery }) => gallery.identifier.id)) { installExtensionHasDependents = installExtensionHasDependents || !!manifest.extensionDependencies?.some(id => areSameExtensions({ id }, installExtensionTask.identifier)); const key = getInstallExtensionTaskKey(gallery); @@ -279,7 +280,7 @@ export abstract class AbstractExtensionManagementService extends Disposable impl })); } } else if (!installed.some(({ identifier }) => areSameExtensions(identifier, gallery.identifier))) { - const task = this.createInstallExtensionTask(manifest, gallery, { ...installExtensionTaskOptions, donotIncludePackAndDependencies: true }); + const task = this.createInstallExtensionTask(manifest, gallery, options); this.installingExtensions.set(key, { task, waitingTasks: [installExtensionTask] }); this._onInstallExtension.fire({ identifier: task.identifier, source: gallery, profileLocation: installExtensionTaskOptions.profileLocation }); this.logService.info('Installing extension:', task.identifier.id, installExtensionTask.identifier.id); @@ -343,12 +344,7 @@ export abstract class AbstractExtensionManagementService extends Disposable impl } } - const context = installExtensionTaskOptions.context ?? {}; - if (hasPackExtensions && task.identifier.id !== installExtensionTask.identifier.id) { - context[EXTENSION_INSTALL_SKIP_WALKTHROUGH_CONTEXT] = true; - } - - installResults.push({ local, identifier: task.identifier, operation: task.operation, source: task.source, context: context, profileLocation: task.profileLocation, applicationScoped: local.isApplicationScoped }); + installResults.push({ local, identifier: task.identifier, operation: task.operation, source: task.source, context: task.options.context, profileLocation: task.profileLocation, applicationScoped: local.isApplicationScoped }); } catch (error) { if (!URI.isUri(task.source)) { reportTelemetry(this.telemetryService, task.operation === InstallOperation.Update ? 'extensionGallery:update' : 'extensionGallery:install', { diff --git a/src/vs/platform/extensionManagement/common/extensionManagement.ts b/src/vs/platform/extensionManagement/common/extensionManagement.ts index 9a9abb281fc..dc4c1ccc02c 100644 --- a/src/vs/platform/extensionManagement/common/extensionManagement.ts +++ b/src/vs/platform/extensionManagement/common/extensionManagement.ts @@ -18,6 +18,7 @@ export const EXTENSION_IDENTIFIER_REGEX = new RegExp(EXTENSION_IDENTIFIER_PATTER export const WEB_EXTENSION_TAG = '__web_extension'; export const EXTENSION_INSTALL_SKIP_WALKTHROUGH_CONTEXT = 'skipWalkthrough'; export const EXTENSION_INSTALL_SYNC_CONTEXT = 'extensionsSync'; +export const EXTENSION_INSTALL_DEP_PACK_CONTEXT = 'dependecyOrPackExtensionInstall'; export function TargetPlatformToString(targetPlatform: TargetPlatform) { switch (targetPlatform) { diff --git a/src/vs/platform/extensionManagement/node/extensionManagementService.ts b/src/vs/platform/extensionManagement/node/extensionManagementService.ts index 6c7b92de0ef..677149f937b 100644 --- a/src/vs/platform/extensionManagement/node/extensionManagementService.ts +++ b/src/vs/platform/extensionManagement/node/extensionManagementService.ts @@ -782,7 +782,7 @@ abstract class InstallExtensionTask extends AbstractExtensionTask { const hadLastFoucs = await this.hostService.hadLastFocus(); for (const e of result) { + const skipWalkthrough = e?.context?.[EXTENSION_INSTALL_SKIP_WALKTHROUGH_CONTEXT] || e?.context?.[EXTENSION_INSTALL_DEP_PACK_CONTEXT]; // If the window had last focus and the install didn't specify to skip the walkthrough // Then add it to the sessionInstallExtensions to be opened - if (hadLastFoucs && !e?.context?.[EXTENSION_INSTALL_SKIP_WALKTHROUGH_CONTEXT]) { + if (hadLastFoucs && !skipWalkthrough) { this.sessionInstalledExtensions.add(e.identifier.id.toLowerCase()); } this.progressByEvent(`extensionInstalled:${e.identifier.id.toLowerCase()}`); diff --git a/src/vs/workbench/services/extensionManagement/common/webExtensionManagementService.ts b/src/vs/workbench/services/extensionManagement/common/webExtensionManagementService.ts index f100b353488..fcff4bbe95c 100644 --- a/src/vs/workbench/services/extensionManagement/common/webExtensionManagementService.ts +++ b/src/vs/workbench/services/extensionManagement/common/webExtensionManagementService.ts @@ -251,7 +251,7 @@ class InstallExtensionTask extends AbstractExtensionTask implem constructor( manifest: IExtensionManifest, private readonly extension: URI | IGalleryExtension, - private readonly options: InstallExtensionTaskOptions, + readonly options: InstallExtensionTaskOptions, private readonly webExtensionsScannerService: IWebExtensionsScannerService, private readonly userDataProfilesService: IUserDataProfilesService, ) { From d5f5ad201dcd9f8568bc2fd35cf48c034385aa55 Mon Sep 17 00:00:00 2001 From: Henning Dieterichs Date: Tue, 22 Aug 2023 17:34:59 +0200 Subject: [PATCH 086/221] Joins consecutive moves that are close together --- src/vs/editor/common/core/lineRange.ts | 8 ++ src/vs/editor/common/core/offsetRange.ts | 12 ++ .../editor/common/diff/linesDiffComputer.ts | 7 ++ .../common/diff/standardLinesDiffComputer.ts | 118 ++++++++++++++---- 4 files changed, 122 insertions(+), 23 deletions(-) diff --git a/src/vs/editor/common/core/lineRange.ts b/src/vs/editor/common/core/lineRange.ts index 568bf03ca2b..73b0f7e5761 100644 --- a/src/vs/editor/common/core/lineRange.ts +++ b/src/vs/editor/common/core/lineRange.ts @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { BugIndicatingError } from 'vs/base/common/errors'; +import { OffsetRange } from 'vs/editor/common/core/offsetRange'; import { Range } from 'vs/editor/common/core/range'; /** @@ -239,6 +240,13 @@ export class LineRange { public includes(lineNumber: number): boolean { return this.startLineNumber <= lineNumber && lineNumber < this.endLineNumberExclusive; } + + /** + * Converts this 1-based line range to a 0-based offset range (subtracts 1!). + */ + public toOffsetRange(): OffsetRange { + return new OffsetRange(this.startLineNumber - 1, this.endLineNumberExclusive - 1); + } } export type ISerializedLineRange = [startLineNumber: number, endLineNumberExclusive: number]; diff --git a/src/vs/editor/common/core/offsetRange.ts b/src/vs/editor/common/core/offsetRange.ts index d46cf88a425..d4129b1c532 100644 --- a/src/vs/editor/common/core/offsetRange.ts +++ b/src/vs/editor/common/core/offsetRange.ts @@ -48,6 +48,14 @@ export class OffsetRange { return new OffsetRange(this.start + offset, this.endExclusive + offset); } + public deltaStart(offset: number): OffsetRange { + return new OffsetRange(this.start + offset, this.endExclusive); + } + + public deltaEnd(offset: number): OffsetRange { + return new OffsetRange(this.start, this.endExclusive + offset); + } + public get length(): number { return this.endExclusive - this.start; } @@ -90,6 +98,10 @@ export class OffsetRange { } return undefined; } + + public slice(arr: T[]): T[] { + return arr.slice(this.start, this.endExclusive); + } } export class OffsetRangeSet { diff --git a/src/vs/editor/common/diff/linesDiffComputer.ts b/src/vs/editor/common/diff/linesDiffComputer.ts index 84505ab563a..d10888cb93f 100644 --- a/src/vs/editor/common/diff/linesDiffComputer.ts +++ b/src/vs/editor/common/diff/linesDiffComputer.ts @@ -155,6 +155,13 @@ export class SimpleLineRangeMapping { public flip(): SimpleLineRangeMapping { return new SimpleLineRangeMapping(this.modified, this.original); } + + public join(other: SimpleLineRangeMapping): SimpleLineRangeMapping { + return new SimpleLineRangeMapping( + this.original.join(other.original), + this.modified.join(other.modified), + ); + } } export class MovedText { diff --git a/src/vs/editor/common/diff/standardLinesDiffComputer.ts b/src/vs/editor/common/diff/standardLinesDiffComputer.ts index b9ef58b85c2..20279a9fe68 100644 --- a/src/vs/editor/common/diff/standardLinesDiffComputer.ts +++ b/src/vs/editor/common/diff/standardLinesDiffComputer.ts @@ -177,7 +177,7 @@ export class StandardLinesDiffComputer implements ILinesDiffComputer { } private computeMoves(changes: LineRangeMapping[], originalLines: string[], modifiedLines: string[], hashedOriginalLines: number[], hashedModifiedLines: number[], timeout: ITimeout, considerWhitespaceChanges: boolean): MovedText[] { - const moves: MovedText[] = []; + const moves: SimpleLineRangeMapping[] = []; const deletions = changes .filter(c => c.modifiedRange.isEmpty && c.originalRange.length >= 3) .map(d => new LineRangeFragment(d.originalRange, originalLines, d)); @@ -199,17 +199,15 @@ export class StandardLinesDiffComputer implements ILinesDiffComputer { } if (highestSimilarity > 0.90 && best) { - const moveChanges = this.refineDiff(originalLines, modifiedLines, new SequenceDiff( - new OffsetRange(deletion.range.startLineNumber - 1, deletion.range.endLineNumberExclusive - 1), - new OffsetRange(best.range.startLineNumber - 1, best.range.endLineNumberExclusive - 1) - ), timeout, considerWhitespaceChanges); - const mappings = lineRangeMappingFromRangeMappings(moveChanges.mappings, originalLines, modifiedLines, true); - insertions.delete(best); - moves.push(new MovedText(new SimpleLineRangeMapping(deletion.range, best.range), mappings)); + moves.push(new SimpleLineRangeMapping(deletion.range, best.range)); excludedChanges.add(deletion.source); excludedChanges.add(best.source); } + + if (!timeout.isValid()) { + return []; + } } const original3LineHashes = new SetMap(); @@ -242,9 +240,6 @@ export class StandardLinesDiffComputer implements ILinesDiffComputer { let lastMappings: PossibleMapping[] = []; for (let i = change.modifiedRange.startLineNumber; i < change.modifiedRange.endLineNumberExclusive - 2; i++) { const key = `${hashedModifiedLines[i - 1]}:${hashedModifiedLines[i + 1 - 1]}:${hashedModifiedLines[i + 2 - 1]}`; - - //const isWeakKey = (originalLines[i].trim().length + originalLines[i + 1].trim().length + originalLines[i + 2].trim().length < 20); - const currentModifiedRange = new LineRange(i, i + 3); const nextMappings: PossibleMapping[] = []; @@ -269,6 +264,10 @@ export class StandardLinesDiffComputer implements ILinesDiffComputer { }); lastMappings = nextMappings; } + + if (!timeout.isValid()) { + return []; + } } possibleMappings.sort(reverseOrder(compareBy(m => m.modifiedLineRange.length, numberComparator))); @@ -291,19 +290,49 @@ export class StandardLinesDiffComputer implements ILinesDiffComputer { const modifiedLineRange = s; const originalLineRange = s.delta(-diffOrigToMod); - const moveChanges = this.refineDiff(originalLines, modifiedLines, new SequenceDiff( - new OffsetRange(originalLineRange.startLineNumber - 1, originalLineRange.endLineNumberExclusive - 1), - new OffsetRange(modifiedLineRange.startLineNumber - 1, modifiedLineRange.endLineNumberExclusive - 1) - ), timeout, considerWhitespaceChanges); - const mappings = lineRangeMappingFromRangeMappings(moveChanges.mappings, originalLines, modifiedLines, true); - moves.push(new MovedText(new SimpleLineRangeMapping(originalLineRange, modifiedLineRange), mappings)); + moves.push(new SimpleLineRangeMapping(originalLineRange, modifiedLineRange)); modifiedSet.addRange(modifiedLineRange); originalSet.addRange(originalLineRange); } } - return moves; + // join moves + moves.sort(compareBy(m => m.original.startLineNumber, numberComparator)); + if (moves.length === 0) { + return []; + } + const joinedMoves = [moves[0]]; + for (let i = 1; i < moves.length; i++) { + const last = joinedMoves[joinedMoves.length - 1]; + const current = moves[i]; + + const originalDist = current.original.startLineNumber - last.original.endLineNumberExclusive; + const modifiedDist = current.modified.startLineNumber - last.modified.endLineNumberExclusive; + const currentMoveAfterLast = originalDist >= 0 && modifiedDist >= 0; + + if (currentMoveAfterLast && originalDist <= 1 && modifiedDist <= 1) { + joinedMoves[joinedMoves.length - 1] = last.join(current); + continue; + } + + const originalText = current.original.toOffsetRange().slice(originalLines).map(l => l.trim()).join('\n'); + if (originalText.length <= 10) { + // Ignore small moves + continue; + } + joinedMoves.push(current); + } + + const fullMoves = joinedMoves.map(m => { + const moveChanges = this.refineDiff(originalLines, modifiedLines, new SequenceDiff( + m.original.toOffsetRange(), + m.modified.toOffsetRange(), + ), timeout, considerWhitespaceChanges); + const mappings = lineRangeMappingFromRangeMappings(moveChanges.mappings, originalLines, modifiedLines, true); + return new MovedText(m, mappings); + }); + return fullMoves; } private refineDiff(originalLines: string[], modifiedLines: string[], diff: SequenceDiff, timeout: ITimeout, considerWhitespaceChanges: boolean): { mappings: RangeMapping[]; hitTimeout: boolean } { @@ -659,7 +688,7 @@ export class LinesSliceCharSequence implements ISequence { private readonly firstCharOffsetByLineMinusOne: number[] = []; public readonly lineRange: OffsetRange; // To account for trimming - private readonly offsetByLine: number[] = []; + private readonly additionalOffsetByLine: number[] = []; constructor(public readonly lines: string[], lineRange: OffsetRange, public readonly considerWhitespaceChanges: boolean) { // This slice has to have lineRange.length many \n! (otherwise diffing against an empty slice will be problematic) @@ -687,7 +716,7 @@ export class LinesSliceCharSequence implements ISequence { line = trimmedStartLine.trimEnd(); } - this.offsetByLine.push(offset); + this.additionalOffsetByLine.push(offset); for (let i = 0; i < line.length; i++) { this.elements.push(line.charCodeAt(i)); @@ -700,7 +729,7 @@ export class LinesSliceCharSequence implements ISequence { } } // To account for the last line - this.offsetByLine.push(0); + this.additionalOffsetByLine.push(0); } toString() { @@ -767,7 +796,7 @@ export class LinesSliceCharSequence implements ISequence { } const offsetOfFirstCharInLine = i === 0 ? 0 : this.firstCharOffsetByLineMinusOne[i - 1]; - return new Position(this.lineRange.start + i + 1, offset - offsetOfFirstCharInLine + 1 + this.offsetByLine[i]); + return new Position(this.lineRange.start + i + 1, offset - offsetOfFirstCharInLine + 1 + this.additionalOffsetByLine[i]); } public translateRange(range: OffsetRange): Range { @@ -805,9 +834,52 @@ export class LinesSliceCharSequence implements ISequence { return this.translateOffset(range.endExclusive).lineNumber - this.translateOffset(range.start).lineNumber; } - isStronglyEqual(offset1: number, offset2: number): boolean { + public isStronglyEqual(offset1: number, offset2: number): boolean { return this.elements[offset1] === this.elements[offset2]; } + + public extendToFullLines(range: OffsetRange): OffsetRange { + const firstIdx = findLastIdxMonotonous(this.firstCharOffsetByLineMinusOne, x => x <= range.start); + const lastIdx = findFirstIdxMonotonous(this.firstCharOffsetByLineMinusOne, x => range.endExclusive <= x); + + const start = firstIdx === -1 ? 0 : this.firstCharOffsetByLineMinusOne[firstIdx]; + const end = lastIdx === this.firstCharOffsetByLineMinusOne.length ? this.elements.length : this.firstCharOffsetByLineMinusOne[lastIdx]; + return new OffsetRange(start, end); + } +} + +/** + * @returns -1 if predicate is false for all items + */ +function findLastIdxMonotonous(arr: T[], predicate: (item: T) => boolean): number { + let i = 0; + let j = arr.length; + while (i < j) { + const k = Math.floor((i + j) / 2); + if (predicate(arr[k])) { + i = k + 1; + } else { + j = k; + } + } + return i - 1; +} + +/** + * @returns arr.length if predicate is false for all items + */ +function findFirstIdxMonotonous(arr: T[], predicate: (item: T) => boolean): number { + let i = 0; + let j = arr.length; + while (i < j) { + const k = Math.floor((i + j) / 2); + if (predicate(arr[k])) { + j = k; + } else { + i = k + 1; + } + } + return i; } function isWordChar(charCode: number): boolean { From 44f9326a27b58188dc51ee925ecdaa75ff3d6559 Mon Sep 17 00:00:00 2001 From: Henning Dieterichs Date: Tue, 22 Aug 2023 17:53:57 +0200 Subject: [PATCH 087/221] Fixes CI --- src/vs/editor/common/core/lineRange.ts | 1 + src/vs/monaco.d.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/src/vs/editor/common/core/lineRange.ts b/src/vs/editor/common/core/lineRange.ts index 73b0f7e5761..70acb0476d6 100644 --- a/src/vs/editor/common/core/lineRange.ts +++ b/src/vs/editor/common/core/lineRange.ts @@ -243,6 +243,7 @@ export class LineRange { /** * Converts this 1-based line range to a 0-based offset range (subtracts 1!). + * @internal */ public toOffsetRange(): OffsetRange { return new OffsetRange(this.startLineNumber - 1, this.endLineNumberExclusive - 1); diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index e6cd4654946..c6b4adf801f 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -2546,6 +2546,7 @@ declare namespace monaco.editor { constructor(original: LineRange, modified: LineRange); toString(): string; flip(): SimpleLineRangeMapping; + join(other: SimpleLineRangeMapping): SimpleLineRangeMapping; } export interface IDimension { width: number; From 94e1fa6de86916a8235f6280a43809d90fc38422 Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 22 Aug 2023 11:40:44 -0700 Subject: [PATCH 088/221] Fix #190968. css variable fallback. --- src/vs/editor/browser/widget/media/diffEditor.css | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/vs/editor/browser/widget/media/diffEditor.css b/src/vs/editor/browser/widget/media/diffEditor.css index 66fa2b5ab83..6d086fe1031 100644 --- a/src/vs/editor/browser/widget/media/diffEditor.css +++ b/src/vs/editor/browser/widget/media/diffEditor.css @@ -81,7 +81,7 @@ } .monaco-editor .line-insert, .monaco-diff-editor .line-insert { - background-color: var(--vscode-diffEditor-insertedLineBackground, --vscode-diffEditor-insertedTextBackground); + background-color: var(--vscode-diffEditor-insertedLineBackground, var(--vscode-diffEditor-insertedTextBackground)); } .monaco-editor .line-insert, @@ -106,7 +106,7 @@ .monaco-editor .inline-added-margin-view-zone, .monaco-editor .gutter-insert, .monaco-diff-editor .gutter-insert { - background-color: var(--vscode-diffEditorGutter-insertedLineBackground, --vscode-diffEditor-insertedLineBackground, --vscode-diffEditor-insertedTextBackground); + background-color: var(--vscode-diffEditorGutter-insertedLineBackground, var(--vscode-diffEditor-insertedLineBackground), var(--vscode-diffEditor-insertedTextBackground)); } .monaco-editor .char-delete, .monaco-diff-editor .char-delete { @@ -114,12 +114,12 @@ } .monaco-editor .line-delete, .monaco-diff-editor .line-delete { - background-color: var(--vscode-diffEditor-removedLineBackground, --vscode-diffEditor-removedTextBackground); + background-color: var(--vscode-diffEditor-removedLineBackground, var(--vscode-diffEditor-removedTextBackground)); } .monaco-editor .inline-deleted-margin-view-zone, .monaco-editor .gutter-delete, .monaco-diff-editor .gutter-delete { - background-color: var(--vscode-diffEditorGutter-removedLineBackground, --vscode-diffEditor-removedLineBackground, --vscode-diffEditor-removedTextBackground); + background-color: var(--vscode-diffEditorGutter-removedLineBackground, var(--vscode-diffEditor-removedLineBackground), var(--vscode-diffEditor-removedTextBackground)); } .monaco-diff-editor.side-by-side .editor.modified { From 6d8b0c45e766114d0efa47a1d5e62a2dec2aa6b7 Mon Sep 17 00:00:00 2001 From: Kartik Raj Date: Tue, 22 Aug 2023 18:51:19 +0000 Subject: [PATCH 089/221] Doc review --- src/vscode-dts/vscode.proposed.envCollectionWorkspace.d.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/vscode-dts/vscode.proposed.envCollectionWorkspace.d.ts b/src/vscode-dts/vscode.proposed.envCollectionWorkspace.d.ts index 43f77834b64..fb4b78e172b 100644 --- a/src/vscode-dts/vscode.proposed.envCollectionWorkspace.d.ts +++ b/src/vscode-dts/vscode.proposed.envCollectionWorkspace.d.ts @@ -25,6 +25,10 @@ declare module 'vscode' { * including the global collection. * * @param scope The scope to which the environment variable collection applies to. + * + * If a scope parameter is omitted, collection applicable to all relevant scopes for that parameter is + * returned. For instance, if the 'workspaceFolder' parameter is not specified, the collection that applies + * across all workspace folders will be returned. */ getScoped(scope: EnvironmentVariableScope): EnvironmentVariableCollection; } From 6a6dc14d4feb6bded3893c7a5f665800aa7bf19a Mon Sep 17 00:00:00 2001 From: Kartik Raj Date: Tue, 22 Aug 2023 18:55:42 +0000 Subject: [PATCH 090/221] Only one new line character in case there is no description --- .../browser/terminal.environmentChanges.contribution.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/contrib/terminalContrib/environmentChanges/browser/terminal.environmentChanges.contribution.ts b/src/vs/workbench/contrib/terminalContrib/environmentChanges/browser/terminal.environmentChanges.contribution.ts index ed59231bb57..e4bcaf9b0c0 100644 --- a/src/vs/workbench/contrib/terminalContrib/environmentChanges/browser/terminal.environmentChanges.contribution.ts +++ b/src/vs/workbench/contrib/terminalContrib/environmentChanges/browser/terminal.environmentChanges.contribution.ts @@ -55,15 +55,14 @@ function describeEnvironmentChanges(collection: IMergedEnvironmentVariableCollec content += '\n'; const globalDescription = globalDescriptions.get(ext); if (globalDescription) { - content += `\n${globalDescription}`; + content += `\n${globalDescription}\n`; } const workspaceDescription = workspaceDescriptions.get(ext); if (workspaceDescription) { // Only show '(workspace)' suffix if there is already a description for the extension. const workspaceSuffix = globalDescription ? ` (${localize('ScopedEnvironmentContributionInfo', 'workspace')})` : ''; - content += `\n${workspaceDescription}${workspaceSuffix}`; + content += `\n${workspaceDescription}${workspaceSuffix}\n`; } - content += '\n'; for (const mutator of coll.map.values()) { if (filterScope(mutator, scope) === false) { From d34d715248d5b107af6d2f98fc560a46637a89cf Mon Sep 17 00:00:00 2001 From: meganrogge Date: Tue, 22 Aug 2023 11:57:36 -0700 Subject: [PATCH 091/221] wip --- .../terminal.accessibility.contribution.ts | 2 +- .../browser/textAreaSyncAddon.ts | 43 +++++++++++++++---- 2 files changed, 35 insertions(+), 10 deletions(-) diff --git a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminal.accessibility.contribution.ts b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminal.accessibility.contribution.ts index b69943c18de..3594567f2b1 100644 --- a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminal.accessibility.contribution.ts +++ b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminal.accessibility.contribution.ts @@ -40,7 +40,7 @@ class TextAreaSyncContribution extends DisposableStore implements ITerminalContr super(); } xtermReady(xterm: IXtermTerminal & { raw: Terminal }): void { - const addon = this._instantiationService.createInstance(TextAreaSyncAddon, this._instance.capabilities); + const addon = this._instantiationService.createInstance(TextAreaSyncAddon, this._instance.capabilities, this._instance.onDidFocus); xterm.raw.loadAddon(addon); addon.activate(xterm.raw); } diff --git a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/textAreaSyncAddon.ts b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/textAreaSyncAddon.ts index 8ed986db3cf..9a52fc9c00a 100644 --- a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/textAreaSyncAddon.ts +++ b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/textAreaSyncAddon.ts @@ -8,6 +8,8 @@ import { IAccessibilityService } from 'vs/platform/accessibility/common/accessib import { ITerminalCapabilityStore, TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities'; import { ITerminalLogService } from 'vs/platform/terminal/common/terminal'; import type { Terminal, ITerminalAddon } from 'xterm'; +import { Event } from 'vs/base/common/event'; +import { ITerminalInstance } from 'vs/workbench/contrib/terminal/browser/terminal'; export interface ITextAreaData { content: string; @@ -17,30 +19,47 @@ export interface ITextAreaData { export class TextAreaSyncAddon extends Disposable implements ITerminalAddon { private _terminal: Terminal | undefined; private _onCursorMoveListener = this._register(new MutableDisposable()); + private _onDidFocusListener = this._register(new MutableDisposable()); + private _onKeyListener = this._register(new MutableDisposable()); activate(terminal: Terminal): void { this._terminal = terminal; if (this._accessibilityService.isScreenReaderOptimized()) { - this._onCursorMoveListener.value = this._terminal.onCursorMove(() => this._refreshTextArea()); + this._setListeners(); } } constructor( private readonly _capabilities: ITerminalCapabilityStore, + private readonly _onDidFocus: Event, @IAccessibilityService private readonly _accessibilityService: IAccessibilityService, @ITerminalLogService private readonly _logService: ITerminalLogService ) { super(); this._register(this._accessibilityService.onDidChangeScreenReaderOptimized(() => { - if (this._accessibilityService.isScreenReaderOptimized() && this._terminal) { + if (this._accessibilityService.isScreenReaderOptimized()) { this._refreshTextArea(); - this._onCursorMoveListener.value = this._terminal.onCursorMove(() => this._refreshTextArea()); + this._setListeners(); } else { this._onCursorMoveListener.clear(); + this._onDidFocusListener.clear(); + this._onKeyListener.clear(); } })); } - private _refreshTextArea(focusChanged?: boolean): void { + private _setListeners(): void { + if (this._accessibilityService.isScreenReaderOptimized() && this._terminal) { + this._onCursorMoveListener.value = this._terminal.onCursorMove(() => this._refreshTextArea()); + this._onDidFocusListener.value = this._onDidFocus(() => this._refreshTextArea()); + this._onKeyListener.value = this._terminal.onKey((e) => { + if (e.domEvent.key === 'UpArrow') { + this._refreshTextArea(); + } + }); + } + } + + private _refreshTextArea(): void { if (!this._terminal) { return; } @@ -59,18 +78,24 @@ export class TextAreaSyncAddon extends Disposable implements ITerminalAddon { return; } let content: string | undefined; - if (currentCommand.commandStartX) { + if (currentCommand.commandStartX !== undefined) { // Left prompt content = line.substring(currentCommand.commandStartX); commandStartX = currentCommand.commandStartX; - } else if (currentCommand.commandRightPromptStartX) { + } else if (currentCommand.commandRightPromptStartX !== undefined) { // Right prompt content = line.substring(0, currentCommand.commandRightPromptStartX); commandStartX = 0; + } else { + this._logService.debug(`TextAreaSyncAddon#refreshTextArea: no commandStartX or commandRightPromptStartX`); } if (!content) { this._logService.debug(`TextAreaSyncAddon#refreshTextArea: no content`); + const textArea = this._terminal.textarea; + if (textArea) { + textArea.textContent = ''; + } return; } @@ -87,15 +112,15 @@ export class TextAreaSyncAddon extends Disposable implements ITerminalAddon { this._logService.debug(`TextAreaSyncAddon#refreshTextArea: content is "${content}"`); this._logService.debug(`TextAreaSyncAddon#refreshTextArea: textContent is "${textArea.textContent}"`); - if (focusChanged || content !== textArea.textContent) { - textArea.textContent = content; + if (content !== textArea.textContent) { + textArea.textContent = content.trim(); this._logService.debug(`TextAreaSyncAddon#refreshTextArea: textContent changed to "${content}"`); } const cursorX = buffer.cursorX - commandStartX; this._logService.debug(`TextAreaSyncAddon#refreshTextArea: cursorX is ${cursorX}`); this._logService.debug(`TextAreaSyncAddon#refreshTextArea: selectionStart is ${textArea.selectionStart}`); - if (focusChanged || cursorX !== textArea.selectionStart) { + if (cursorX !== textArea.selectionStart) { textArea.selectionStart = cursorX; textArea.selectionEnd = cursorX; this._logService.debug(`TextAreaSyncAddon#refreshTextArea: selectionStart changed to ${cursorX}`); From f058931630bec023da5ea0ae633262f9ebe50703 Mon Sep 17 00:00:00 2001 From: Tyler James Leonhardt Date: Tue, 22 Aug 2023 12:22:53 -0700 Subject: [PATCH 092/221] RelatedInformation & EmbeddingVector API (#191006) --- .../api/browser/extensionHost.contribution.ts | 2 + .../browser/mainThreadAiEmbeddingVector.ts | 41 +++++++ .../browser/mainThreadAiRelatedInformation.ts | 44 +++++++ .../workbench/api/common/extHost.api.impl.ts | 19 ++- .../workbench/api/common/extHost.protocol.ts | 24 ++++ .../api/common/extHostAiRelatedInformation.ts | 50 ++++++++ .../api/common/extHostEmbeddingVector.ts | 50 ++++++++ src/vs/workbench/api/common/extHostTypes.ts | 11 ++ .../browser/commandsQuickAccess.ts | 88 ++++++++++---- .../common/aiEmbeddingVectorService.ts | 114 ++++++++++++++++++ .../common/aiRelatedInformation.ts | 39 ++++++ .../common/aiRelatedInformationService.ts | 114 ++++++++++++++++++ .../common/extensionsApiProposals.ts | 1 + src/vs/workbench/workbench.common.main.ts | 2 + .../vscode.proposed.aiRelatedInformation.d.ts | 62 ++++++++++ 15 files changed, 638 insertions(+), 23 deletions(-) create mode 100644 src/vs/workbench/api/browser/mainThreadAiEmbeddingVector.ts create mode 100644 src/vs/workbench/api/browser/mainThreadAiRelatedInformation.ts create mode 100644 src/vs/workbench/api/common/extHostAiRelatedInformation.ts create mode 100644 src/vs/workbench/api/common/extHostEmbeddingVector.ts create mode 100644 src/vs/workbench/services/aiEmbeddingVector/common/aiEmbeddingVectorService.ts create mode 100644 src/vs/workbench/services/aiRelatedInformation/common/aiRelatedInformation.ts create mode 100644 src/vs/workbench/services/aiRelatedInformation/common/aiRelatedInformationService.ts create mode 100644 src/vscode-dts/vscode.proposed.aiRelatedInformation.d.ts diff --git a/src/vs/workbench/api/browser/extensionHost.contribution.ts b/src/vs/workbench/api/browser/extensionHost.contribution.ts index 774cc0cc158..8a71fe97ce1 100644 --- a/src/vs/workbench/api/browser/extensionHost.contribution.ts +++ b/src/vs/workbench/api/browser/extensionHost.contribution.ts @@ -88,6 +88,8 @@ import './mainThreadSecretState'; import './mainThreadShare'; import './mainThreadProfilContentHandlers'; import './mainThreadSemanticSimilarity'; +import './mainThreadAiRelatedInformation'; +import './mainThreadAiEmbeddingVector'; import './mainThreadIssueReporter'; export class ExtensionPoints implements IWorkbenchContribution { diff --git a/src/vs/workbench/api/browser/mainThreadAiEmbeddingVector.ts b/src/vs/workbench/api/browser/mainThreadAiEmbeddingVector.ts new file mode 100644 index 00000000000..954679e2c52 --- /dev/null +++ b/src/vs/workbench/api/browser/mainThreadAiEmbeddingVector.ts @@ -0,0 +1,41 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { CancellationToken } from 'vs/base/common/cancellation'; +import { Disposable, DisposableMap } from 'vs/base/common/lifecycle'; +import { ExtHostAiEmbeddingVectorShape, ExtHostContext, MainContext, MainThreadAiEmbeddingVectorShape } from 'vs/workbench/api/common/extHost.protocol'; +import { IAiEmbeddingVectorProvider, IAiEmbeddingVectorService } from 'vs/workbench/services/aiEmbeddingVector/common/aiEmbeddingVectorService'; +import { IExtHostContext, extHostNamedCustomer } from 'vs/workbench/services/extensions/common/extHostCustomers'; + +@extHostNamedCustomer(MainContext.MainThreadAiEmbeddingVector) +export class MainThreadAiEmbeddingVector extends Disposable implements MainThreadAiEmbeddingVectorShape { + private readonly _proxy: ExtHostAiEmbeddingVectorShape; + private readonly _registrations = this._register(new DisposableMap()); + + constructor( + context: IExtHostContext, + @IAiEmbeddingVectorService private readonly _AiEmbeddingVectorService: IAiEmbeddingVectorService, + ) { + super(); + this._proxy = context.getProxy(ExtHostContext.ExtHostAiEmbeddingVector); + } + + $registerAiEmbeddingVectorProvider(model: string, handle: number): void { + const provider: IAiEmbeddingVectorProvider = { + provideAiEmbeddingVector: (strings: string[], token: CancellationToken) => { + return this._proxy.$provideAiEmbeddingVector( + handle, + strings, + token + ); + }, + }; + this._registrations.set(handle, this._AiEmbeddingVectorService.registerAiEmbeddingVectorProvider(model, provider)); + } + + $unregisterAiEmbeddingVectorProvider(handle: number): void { + this._registrations.deleteAndDispose(handle); + } +} diff --git a/src/vs/workbench/api/browser/mainThreadAiRelatedInformation.ts b/src/vs/workbench/api/browser/mainThreadAiRelatedInformation.ts new file mode 100644 index 00000000000..b198f41be47 --- /dev/null +++ b/src/vs/workbench/api/browser/mainThreadAiRelatedInformation.ts @@ -0,0 +1,44 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { CancellationToken } from 'vs/base/common/cancellation'; +import { Disposable, DisposableMap } from 'vs/base/common/lifecycle'; +import { ExtHostAiRelatedInformationShape, ExtHostContext, MainContext, MainThreadAiRelatedInformationShape } from 'vs/workbench/api/common/extHost.protocol'; +import { RelatedInformationType } from 'vs/workbench/api/common/extHostTypes'; +import { IAiRelatedInformationProvider, IAiRelatedInformationService } from 'vs/workbench/services/aiRelatedInformation/common/aiRelatedInformation'; +import { IExtHostContext, extHostNamedCustomer } from 'vs/workbench/services/extensions/common/extHostCustomers'; +import { RelatedInformationResult } from 'vscode'; + +@extHostNamedCustomer(MainContext.MainThreadAiRelatedInformation) +export class MainThreadAiRelatedInformation extends Disposable implements MainThreadAiRelatedInformationShape { + private readonly _proxy: ExtHostAiRelatedInformationShape; + private readonly _registrations = this._register(new DisposableMap()); + + constructor( + context: IExtHostContext, + @IAiRelatedInformationService private readonly _aiRelatedInformationService: IAiRelatedInformationService, + ) { + super(); + this._proxy = context.getProxy(ExtHostContext.ExtHostAiRelatedInformation); + } + + $getAiRelatedInformation(query: string, types: RelatedInformationType[]): Promise { + // TODO: use a real cancellation token + return this._aiRelatedInformationService.getRelatedInformation(query, types, CancellationToken.None); + } + + $registerAiRelatedInformationProvider(handle: number, types: RelatedInformationType[]): void { + const provider: IAiRelatedInformationProvider = { + provideAiRelatedInformation: (query, types, token) => { + return this._proxy.$provideAiRelatedInformation(handle, query, types, token); + }, + }; + this._registrations.set(handle, this._aiRelatedInformationService.registerAiRelatedInformationProvider(types, provider)); + } + + $unregisterAiRelatedInformationProvider(handle: number): void { + this._registrations.deleteAndDispose(handle); + } +} diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index 291edaf4e33..b3656684769 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -107,6 +107,8 @@ import { ExtHostShare } from 'vs/workbench/api/common/extHostShare'; import { ExtHostChatProvider } from 'vs/workbench/api/common/extHostChatProvider'; import { ExtHostChatSlashCommands } from 'vs/workbench/api/common/extHostChatSlashCommand'; import { ExtHostChatVariables } from 'vs/workbench/api/common/extHostChatVariables'; +import { ExtHostRelatedInformation } from 'vs/workbench/api/common/extHostAiRelatedInformation'; +import { ExtHostAiEmbeddingVector } from 'vs/workbench/api/common/extHostEmbeddingVector'; export interface IExtensionRegistries { mine: ExtensionDescriptionRegistry; @@ -211,6 +213,8 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I const extHostChatVariables = rpcProtocol.set(ExtHostContext.ExtHostChatVariables, new ExtHostChatVariables(rpcProtocol)); const extHostChat = rpcProtocol.set(ExtHostContext.ExtHostChat, new ExtHostChat(rpcProtocol, extHostLogService)); const extHostSemanticSimilarity = rpcProtocol.set(ExtHostContext.ExtHostSemanticSimilarity, new ExtHostSemanticSimilarity(rpcProtocol)); + const extHostAiRelatedInformation = rpcProtocol.set(ExtHostContext.ExtHostAiRelatedInformation, new ExtHostRelatedInformation(rpcProtocol)); + const extHostAiEmbeddingVector = rpcProtocol.set(ExtHostContext.ExtHostAiEmbeddingVector, new ExtHostAiEmbeddingVector(rpcProtocol)); const extHostIssueReporter = rpcProtocol.set(ExtHostContext.ExtHostIssueReporter, new ExtHostIssueReporter(rpcProtocol)); const extHostStatusBar = rpcProtocol.set(ExtHostContext.ExtHostStatusBar, new ExtHostStatusBar(rpcProtocol, extHostCommands.converter)); @@ -1323,6 +1327,18 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I registerSemanticSimilarityProvider(provider: vscode.SemanticSimilarityProvider) { checkProposedApiEnabled(extension, 'semanticSimilarity'); return extHostSemanticSimilarity.registerSemanticSimilarityProvider(extension, provider); + }, + getRelatedInformation(query: string, types: vscode.RelatedInformationType[]): Thenable { + checkProposedApiEnabled(extension, 'aiRelatedInformation'); + return extHostAiRelatedInformation.getRelatedInformation(extension, query, types); + }, + registerRelatedInformationProvider(types: vscode.RelatedInformationType[], provider: vscode.RelatedInformationProvider) { + checkProposedApiEnabled(extension, 'aiRelatedInformation'); + return extHostAiRelatedInformation.registerRelatedInformationProvider(extension, types, provider); + }, + registerEmbeddingVectorProvider(model: string, provider: vscode.EmbeddingVectorProvider) { + checkProposedApiEnabled(extension, 'aiRelatedInformation'); + return extHostAiEmbeddingVector.registerEmbeddingVectorProvider(extension, model, provider); } }; @@ -1560,7 +1576,8 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I InteractiveEditorResponseFeedbackKind: extHostTypes.InteractiveEditorResponseFeedbackKind, StackFrameFocus: extHostTypes.StackFrameFocus, ThreadFocus: extHostTypes.ThreadFocus, - NotebookCodeActionKind: extHostTypes.NotebookCodeActionKind + NotebookCodeActionKind: extHostTypes.NotebookCodeActionKind, + RelatedInformationType: extHostTypes.RelatedInformationType }; }; } diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index 6886d86e0a9..3ed42880b48 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -76,6 +76,7 @@ import { ISaveProfileResult } from 'vs/workbench/services/userDataProfile/common import { IChatMessage, IChatResponseFragment, IChatResponseProviderMetadata } from 'vs/workbench/contrib/chat/common/chatProvider'; import { IChatSlashFragment } from 'vs/workbench/contrib/chat/common/chatSlashCommands'; import { IChatRequestVariableValue, IChatVariableData } from 'vs/workbench/contrib/chat/common/chatVariables'; +import { RelatedInformationResult, RelatedInformationType } from 'vs/workbench/services/aiRelatedInformation/common/aiRelatedInformation'; export interface IWorkspaceData extends IStaticWorkspaceData { folders: { uri: UriComponents; name: string; index: number }[]; @@ -1662,6 +1663,25 @@ export interface MainThreadSemanticSimilarityShape extends IDisposable { $unregisterSemanticSimilarityProvider(handle: number): void; } +export interface ExtHostAiRelatedInformationShape { + $provideAiRelatedInformation(handle: number, query: string, types: RelatedInformationType[], token: CancellationToken): Promise; +} + +export interface MainThreadAiRelatedInformationShape { + $getAiRelatedInformation(query: string, types: RelatedInformationType[]): Promise; + $registerAiRelatedInformationProvider(handle: number, types: RelatedInformationType[]): void; + $unregisterAiRelatedInformationProvider(handle: number): void; +} + +export interface ExtHostAiEmbeddingVectorShape { + $provideAiEmbeddingVector(handle: number, strings: string[], token: CancellationToken): Promise; +} + +export interface MainThreadAiEmbeddingVectorShape { + $registerAiEmbeddingVectorProvider(model: string, handle: number): void; + $unregisterAiEmbeddingVectorProvider(handle: number): void; +} + export interface ExtHostSecretStateShape { $onDidChangePassword(e: { extensionId: string; key: string }): Promise; } @@ -2641,6 +2661,8 @@ export const MainContext = { MainThreadTesting: createProxyIdentifier('MainThreadTesting'), MainThreadLocalization: createProxyIdentifier('MainThreadLocalizationShape'), MainThreadSemanticSimilarity: createProxyIdentifier('MainThreadSemanticSimilarity'), + MainThreadAiRelatedInformation: createProxyIdentifier('MainThreadAiRelatedInformation'), + MainThreadAiEmbeddingVector: createProxyIdentifier('MainThreadAiEmbeddingVector'), MainThreadIssueReporter: createProxyIdentifier('MainThreadIssueReporter'), }; @@ -2701,6 +2723,8 @@ export const ExtHostContext = { ExtHostChatVariables: createProxyIdentifier('ExtHostChatVariables'), ExtHostChatProvider: createProxyIdentifier('ExtHostChatProvider'), ExtHostSemanticSimilarity: createProxyIdentifier('ExtHostSemanticSimilarity'), + ExtHostAiRelatedInformation: createProxyIdentifier('ExtHostAiRelatedInformation'), + ExtHostAiEmbeddingVector: createProxyIdentifier('ExtHostAiEmbeddingVector'), ExtHostTheming: createProxyIdentifier('ExtHostTheming'), ExtHostTunnelService: createProxyIdentifier('ExtHostTunnelService'), ExtHostManagedSockets: createProxyIdentifier('ExtHostManagedSockets'), diff --git a/src/vs/workbench/api/common/extHostAiRelatedInformation.ts b/src/vs/workbench/api/common/extHostAiRelatedInformation.ts new file mode 100644 index 00000000000..9dc39e42ae1 --- /dev/null +++ b/src/vs/workbench/api/common/extHostAiRelatedInformation.ts @@ -0,0 +1,50 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { IExtensionDescription } from 'vs/platform/extensions/common/extensions'; +import { ExtHostAiRelatedInformationShape, IMainContext, MainContext, MainThreadAiRelatedInformationShape } from 'vs/workbench/api/common/extHost.protocol'; +import type { CancellationToken, RelatedInformationProvider, RelatedInformationResult, RelatedInformationType } from 'vscode'; +import { Disposable } from 'vs/workbench/api/common/extHostTypes'; + +export class ExtHostRelatedInformation implements ExtHostAiRelatedInformationShape { + private _relatedInformationProviders: Map = new Map(); + private _nextHandle = 0; + + private readonly _proxy: MainThreadAiRelatedInformationShape; + + constructor(mainContext: IMainContext) { + this._proxy = mainContext.getProxy(MainContext.MainThreadAiRelatedInformation); + } + + async $provideAiRelatedInformation(handle: number, query: string, types: RelatedInformationType[], token: CancellationToken): Promise { + if (this._relatedInformationProviders.size === 0) { + throw new Error('No semantic similarity providers registered'); + } + + const provider = this._relatedInformationProviders.get(handle); + if (!provider) { + throw new Error('Semantic similarity provider not found'); + } + + // TODO: should this return undefined or an empty array? + const result = await provider.provideRelatedInformation(query, types, token) ?? []; + return result; + } + + getRelatedInformation(extension: IExtensionDescription, query: string, types: RelatedInformationType[]): Promise { + return this._proxy.$getAiRelatedInformation(query, types); + } + + registerRelatedInformationProvider(extension: IExtensionDescription, types: RelatedInformationType[], provider: RelatedInformationProvider): Disposable { + const handle = this._nextHandle; + this._nextHandle++; + this._relatedInformationProviders.set(handle, provider); + this._proxy.$registerAiRelatedInformationProvider(handle, types); + return new Disposable(() => { + this._proxy.$unregisterAiRelatedInformationProvider(handle); + this._relatedInformationProviders.delete(handle); + }); + } +} diff --git a/src/vs/workbench/api/common/extHostEmbeddingVector.ts b/src/vs/workbench/api/common/extHostEmbeddingVector.ts new file mode 100644 index 00000000000..20b3bcb266b --- /dev/null +++ b/src/vs/workbench/api/common/extHostEmbeddingVector.ts @@ -0,0 +1,50 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { IExtensionDescription } from 'vs/platform/extensions/common/extensions'; +import { ExtHostAiEmbeddingVectorShape, IMainContext, MainContext, MainThreadAiEmbeddingVectorShape } from 'vs/workbench/api/common/extHost.protocol'; +import type { CancellationToken, EmbeddingVectorProvider } from 'vscode'; +import { Disposable } from 'vs/workbench/api/common/extHostTypes'; + +export class ExtHostAiEmbeddingVector implements ExtHostAiEmbeddingVectorShape { + private _AiEmbeddingVectorProviders: Map = new Map(); + private _nextHandle = 0; + + private readonly _proxy: MainThreadAiEmbeddingVectorShape; + + constructor( + mainContext: IMainContext + ) { + this._proxy = mainContext.getProxy(MainContext.MainThreadAiEmbeddingVector); + } + + async $provideAiEmbeddingVector(handle: number, strings: string[], token: CancellationToken): Promise { + if (this._AiEmbeddingVectorProviders.size === 0) { + throw new Error('No embedding vector providers registered'); + } + + const provider = this._AiEmbeddingVectorProviders.get(handle); + if (!provider) { + throw new Error('Embedding vector provider not found'); + } + + const result = await provider.provideEmbeddingVector(strings, token); + if (!result) { + throw new Error('Embedding vector provider returned undefined'); + } + return result; + } + + registerEmbeddingVectorProvider(extension: IExtensionDescription, model: string, provider: EmbeddingVectorProvider): Disposable { + const handle = this._nextHandle; + this._nextHandle++; + this._AiEmbeddingVectorProviders.set(handle, provider); + this._proxy.$registerAiEmbeddingVectorProvider(model, handle); + return new Disposable(() => { + this._proxy.$unregisterAiEmbeddingVectorProvider(handle); + this._AiEmbeddingVectorProviders.delete(handle); + }); + } +} diff --git a/src/vs/workbench/api/common/extHostTypes.ts b/src/vs/workbench/api/common/extHostTypes.ts index 2f2bba71433..ac36411c043 100644 --- a/src/vs/workbench/api/common/extHostTypes.ts +++ b/src/vs/workbench/api/common/extHostTypes.ts @@ -4117,3 +4117,14 @@ export class ChatMessage implements vscode.ChatMessage { } //#endregion + +//#region ai + +export enum RelatedInformationType { + SymbolInformation = 1, + CommandInformation = 2, + SearchInformation = 3, + SettingInformation = 4 +} + +//#endregion diff --git a/src/vs/workbench/contrib/quickaccess/browser/commandsQuickAccess.ts b/src/vs/workbench/contrib/quickaccess/browser/commandsQuickAccess.ts index dd837a29ec7..4df3b8e287f 100644 --- a/src/vs/workbench/contrib/quickaccess/browser/commandsQuickAccess.ts +++ b/src/vs/workbench/contrib/quickaccess/browser/commandsQuickAccess.ts @@ -36,6 +36,7 @@ import { IProductService } from 'vs/platform/product/common/productService'; import { ISemanticSimilarityService } from 'vs/workbench/services/semanticSimilarity/common/semanticSimilarityService'; import { IChatService } from 'vs/workbench/contrib/chat/common/chatService'; import { ASK_QUICK_QUESTION_ACTION_ID } from 'vs/workbench/contrib/chat/browser/actions/chatQuickInputActions'; +import { CommandInformationResult, IAiRelatedInformationService, RelatedInformationType } from 'vs/workbench/services/aiRelatedInformation/common/aiRelatedInformation'; export class CommandsQuickAccessProvider extends AbstractEditorCommandsQuickAccessProvider { @@ -75,6 +76,7 @@ export class CommandsQuickAccessProvider extends AbstractEditorCommandsQuickAcce @IPreferencesService private readonly preferencesService: IPreferencesService, @IProductService private readonly productService: IProductService, @ISemanticSimilarityService private readonly semanticSimilarityService: ISemanticSimilarityService, + @IAiRelatedInformationService private readonly aiRelatedInformationService: IAiRelatedInformationService, @IChatService private readonly chatService: IChatService ) { super({ @@ -137,7 +139,12 @@ export class CommandsQuickAccessProvider extends AbstractEditorCommandsQuickAcce } protected hasAdditionalCommandPicks(filter: string, token: CancellationToken): boolean { - if (!this.useSemanticSimilarity || filter === '' || token.isCancellationRequested || !this.semanticSimilarityService.isEnabled()) { + if ( + !this.useSemanticSimilarity + || token.isCancellationRequested + || filter === '' + || !(this.semanticSimilarityService.isEnabled() || this.aiRelatedInformationService.isEnabled()) + ) { return false; } @@ -149,16 +156,49 @@ export class CommandsQuickAccessProvider extends AbstractEditorCommandsQuickAcce return []; } - const format = allPicks.map(p => p.commandId); - let scores: number[]; + let additionalPicks; + try { // Wait a bit to see if the user is still typing await timeout(CommandsQuickAccessProvider.SEMANTIC_SIMILARITY_DEBOUNCE, token); - scores = await this.semanticSimilarityService.getSimilarityScore(filter, format, token); + additionalPicks = this.aiRelatedInformationService.isEnabled() + ? await this.getRelatedInformationPicks(allPicks, picksSoFar, filter, token) + : this.semanticSimilarityService.isEnabled() + ? await this.getSemanticSimilarityPicks(allPicks, picksSoFar, filter, token) + : []; } catch (e) { return []; } + if (additionalPicks.length) { + additionalPicks.unshift({ + type: 'separator', + label: localize('semanticSimilarity', "similar commands") + }); + } + + if (picksSoFar.length || additionalPicks.length) { + additionalPicks.push({ + type: 'separator' + }); + } + + const info = this.chatService.getProviderInfos()[0]; + if (info) { + additionalPicks.push({ + label: localize('askXInChat', "Ask {0}: {1}", info.displayName, filter), + commandId: ASK_QUICK_QUESTION_ACTION_ID, + args: [filter] + }); + } + + return additionalPicks; + } + + private async getSemanticSimilarityPicks(allPicks: ICommandQuickPick[], picksSoFar: ICommandQuickPick[], filter: string, token: CancellationToken) { + const format = allPicks.map(p => p.commandId); + const scores = await this.semanticSimilarityService.getSimilarityScore(filter, format, token); + if (token.isCancellationRequested) { return []; } @@ -181,26 +221,30 @@ export class CommandsQuickAccessProvider extends AbstractEditorCommandsQuickAcce } } - if (numOfSmartPicks) { - additionalPicks.unshift({ - type: 'separator', - label: localize('semanticSimilarity', "similar commands") - }); - } + return additionalPicks; + } - if (picksSoFar.length || additionalPicks.length) { - additionalPicks.push({ - type: 'separator' - }); - } + private async getRelatedInformationPicks(allPicks: ICommandQuickPick[], picksSoFar: ICommandQuickPick[], filter: string, token: CancellationToken) { + const relatedInformation = await this.aiRelatedInformationService.getRelatedInformation( + filter, + [RelatedInformationType.CommandInformation], + token + ) as CommandInformationResult[]; - const info = this.chatService.getProviderInfos()[0]; - if (info) { - additionalPicks.push({ - label: localize('askXInChat', "Ask {0}: {1}", info.displayName, filter), - commandId: ASK_QUICK_QUESTION_ACTION_ID, - args: [filter] - }); + // Sort by weight descending to get the most relevant results first + relatedInformation.sort((a, b) => b.weight - a.weight); + + const setOfPicksSoFar = new Set(picksSoFar.map(p => p.commandId)); + const additionalPicks = new Array(); + + for (const info of relatedInformation) { + if (info.weight < CommandsQuickAccessProvider.SEMANTIC_SIMILARITY_THRESHOLD || additionalPicks.length === CommandsQuickAccessProvider.SEMANTIC_SIMILARITY_MAX_PICKS) { + break; + } + const pick = allPicks.find(p => p.commandId === info.command && !setOfPicksSoFar.has(p.commandId)); + if (pick) { + additionalPicks.push(pick); + } } return additionalPicks; diff --git a/src/vs/workbench/services/aiEmbeddingVector/common/aiEmbeddingVectorService.ts b/src/vs/workbench/services/aiEmbeddingVector/common/aiEmbeddingVectorService.ts new file mode 100644 index 00000000000..bb143a48893 --- /dev/null +++ b/src/vs/workbench/services/aiEmbeddingVector/common/aiEmbeddingVectorService.ts @@ -0,0 +1,114 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; +import { CancellationToken } from 'vs/base/common/cancellation'; +import { CancelablePromise, createCancelablePromise, raceCancellablePromises, timeout } from 'vs/base/common/async'; +import { IDisposable } from 'vs/base/common/lifecycle'; +import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions'; +import { StopWatch } from 'vs/base/common/stopwatch'; +import { ILogService } from 'vs/platform/log/common/log'; + +export const IAiEmbeddingVectorService = createDecorator('IAiEmbeddingVectorService'); + +export interface IAiEmbeddingVectorService { + readonly _serviceBrand: undefined; + + isEnabled(): boolean; + getEmbeddingVector(str: string, token: CancellationToken): Promise; + getEmbeddingVector(strings: string[], token: CancellationToken): Promise; + registerAiEmbeddingVectorProvider(model: string, provider: IAiEmbeddingVectorProvider): IDisposable; +} + +export interface IAiEmbeddingVectorProvider { + provideAiEmbeddingVector(strings: string[], token: CancellationToken): Promise; +} + +export class AiEmbeddingVectorService implements IAiEmbeddingVectorService { + readonly _serviceBrand: undefined; + + static readonly DEFAULT_TIMEOUT = 1000 * 10; // 10 seconds + + private readonly _providers: IAiEmbeddingVectorProvider[] = []; + + constructor(@ILogService private readonly logService: ILogService) { } + + isEnabled(): boolean { + return this._providers.length > 0; + } + + registerAiEmbeddingVectorProvider(model: string, provider: IAiEmbeddingVectorProvider): IDisposable { + this._providers.push(provider); + return { + dispose: () => { + const index = this._providers.indexOf(provider); + if (index >= 0) { + this._providers.splice(index, 1); + } + } + }; + } + + getEmbeddingVector(str: string, token: CancellationToken): Promise; + getEmbeddingVector(strings: string[], token: CancellationToken): Promise; + async getEmbeddingVector(strings: string | string[], token: CancellationToken): Promise { + if (this._providers.length === 0) { + throw new Error('No embedding vector providers registered'); + } + + const stopwatch = StopWatch.create(); + + const cancellablePromises: Array> = []; + + const timer = timeout(AiEmbeddingVectorService.DEFAULT_TIMEOUT); + const disposable = token.onCancellationRequested(() => { + disposable.dispose(); + timer.cancel(); + }); + + for (const provider of this._providers) { + cancellablePromises.push(createCancelablePromise(async t => { + try { + return await provider.provideAiEmbeddingVector( + Array.isArray(strings) ? strings : [strings], + t + ); + } catch (e) { + // logged in extension host + } + // Wait for the timer to finish to allow for another provider to resolve. + // Alternatively, if something resolved, or we've timed out, this will throw + // as expected. + await timer; + throw new Error('Embedding vector provider timed out'); + })); + } + + cancellablePromises.push(createCancelablePromise(async (t) => { + const disposable = t.onCancellationRequested(() => { + timer.cancel(); + disposable.dispose(); + }); + await timer; + throw new Error('Embedding vector provider timed out'); + })); + + try { + const result = await raceCancellablePromises(cancellablePromises); + + // If we have a single result, return it directly, otherwise return an array. + // This aligns with the API overloads. + if (result.length === 1) { + return result[0]; + } + return result; + } finally { + stopwatch.stop(); + this.logService.trace(`[AiEmbeddingVectorService]: getEmbeddingVector took ${stopwatch.elapsed()}ms`); + } + } +} + +registerSingleton(IAiEmbeddingVectorService, AiEmbeddingVectorService, InstantiationType.Delayed); diff --git a/src/vs/workbench/services/aiRelatedInformation/common/aiRelatedInformation.ts b/src/vs/workbench/services/aiRelatedInformation/common/aiRelatedInformation.ts new file mode 100644 index 00000000000..75248fb38d5 --- /dev/null +++ b/src/vs/workbench/services/aiRelatedInformation/common/aiRelatedInformation.ts @@ -0,0 +1,39 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { CancellationToken } from 'vs/base/common/cancellation'; +import { IDisposable } from 'vs/base/common/lifecycle'; +import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; + +export const IAiRelatedInformationService = createDecorator('IAiRelatedInformationService'); + +export enum RelatedInformationType { + SymbolInformation = 1, + CommandInformation = 2, + SearchInformation = 3, + SettingInformation = 4 +} + +export interface RelatedInformationResult { + type: RelatedInformationType; + weight: number; +} + +export interface CommandInformationResult extends RelatedInformationResult { + type: RelatedInformationType.CommandInformation; + command: string; +} + +export interface IAiRelatedInformationService { + readonly _serviceBrand: undefined; + + isEnabled(): boolean; + getRelatedInformation(query: string, types: RelatedInformationType[], token: CancellationToken): Promise; + registerAiRelatedInformationProvider(types: RelatedInformationType[], provider: IAiRelatedInformationProvider): IDisposable; +} + +export interface IAiRelatedInformationProvider { + provideAiRelatedInformation(query: string, types: RelatedInformationType[], token: CancellationToken): Promise; +} diff --git a/src/vs/workbench/services/aiRelatedInformation/common/aiRelatedInformationService.ts b/src/vs/workbench/services/aiRelatedInformation/common/aiRelatedInformationService.ts new file mode 100644 index 00000000000..e0309ff37d1 --- /dev/null +++ b/src/vs/workbench/services/aiRelatedInformation/common/aiRelatedInformationService.ts @@ -0,0 +1,114 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { CancellationToken } from 'vs/base/common/cancellation'; +import { CancelablePromise, createCancelablePromise, raceCancellablePromises, timeout } from 'vs/base/common/async'; +import { IDisposable } from 'vs/base/common/lifecycle'; +import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions'; +import { StopWatch } from 'vs/base/common/stopwatch'; +import { ILogService } from 'vs/platform/log/common/log'; +import { IAiRelatedInformationService, IAiRelatedInformationProvider, RelatedInformationType, RelatedInformationResult } from 'vs/workbench/services/aiRelatedInformation/common/aiRelatedInformation'; + +export class AiRelatedInformationService implements IAiRelatedInformationService { + readonly _serviceBrand: undefined; + + static readonly DEFAULT_TIMEOUT = 1000 * 10; // 10 seconds + + private readonly _providers: Map = new Map(); + + constructor(@ILogService private readonly logService: ILogService) { } + + isEnabled(): boolean { + return this._providers.size > 0; + } + + registerAiRelatedInformationProvider(types: RelatedInformationType[], provider: IAiRelatedInformationProvider): IDisposable { + for (const type of types) { + const providers = this._providers.get(type) ?? []; + providers.push(provider); + this._providers.set(type, providers); + } + + return { + dispose: () => { + for (const type of types) { + const providers = this._providers.get(type) ?? []; + const index = providers.indexOf(provider); + if (index !== -1) { + providers.splice(index, 1); + } + if (providers.length === 0) { + this._providers.delete(type); + } + } + } + }; + } + + async getRelatedInformation(query: string, types: RelatedInformationType[], token: CancellationToken): Promise { + if (this._providers.size === 0) { + throw new Error('No related information providers registered'); + } + + // get providers for each type + const providers: IAiRelatedInformationProvider[] = []; + for (const type of types) { + const typeProviders = this._providers.get(type); + if (typeProviders) { + providers.push(...typeProviders); + } + } + + if (providers.length === 0) { + throw new Error('No related information providers registered for the given types'); + } + + const stopwatch = StopWatch.create(); + + const cancellablePromises: Array> = []; + + const timer = timeout(AiRelatedInformationService.DEFAULT_TIMEOUT); + const disposable = token.onCancellationRequested(() => { + disposable.dispose(); + timer.cancel(); + }); + + for (const provider of providers) { + cancellablePromises.push(createCancelablePromise(async t => { + try { + const result = await provider.provideAiRelatedInformation(query, types, t); + // double filter just in case + return result.filter(r => types.includes(r.type)); + } catch (e) { + // logged in extension host + } + // Wait for the timer to finish to allow for another provider to resolve. + // Alternatively, if something resolved, or we've timed out, this will throw + // as expected. + await timer; + throw new Error('Related information provider timed out'); + })); + } + + cancellablePromises.push(createCancelablePromise(async (t) => { + const disposable = t.onCancellationRequested(() => { + timer.cancel(); + disposable.dispose(); + }); + await timer; + throw new Error('Related information provider timed out'); + })); + + try { + const result = await raceCancellablePromises(cancellablePromises); + return result; + } finally { + stopwatch.stop(); + this.logService.trace(`[AiRelatedInformationService]: getRelatedInformation took ${stopwatch.elapsed()}ms`); + } + } +} + +registerSingleton(IAiRelatedInformationService, AiRelatedInformationService, InstantiationType.Delayed); diff --git a/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts b/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts index f3dc351a3a5..8b1cba0367d 100644 --- a/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts +++ b/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts @@ -6,6 +6,7 @@ // THIS IS A GENERATED FILE. DO NOT EDIT DIRECTLY. export const allApiProposals = Object.freeze({ + aiRelatedInformation: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.aiRelatedInformation.d.ts', authGetSessions: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.authGetSessions.d.ts', authSession: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.authSession.d.ts', canonicalUriProvider: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.canonicalUriProvider.d.ts', diff --git a/src/vs/workbench/workbench.common.main.ts b/src/vs/workbench/workbench.common.main.ts index a52b2b4c274..13cdbab8e9c 100644 --- a/src/vs/workbench/workbench.common.main.ts +++ b/src/vs/workbench/workbench.common.main.ts @@ -68,6 +68,8 @@ import 'vs/workbench/services/configuration/common/jsonEditingService'; import 'vs/workbench/services/textmodelResolver/common/textModelResolverService'; import 'vs/workbench/services/editor/browser/editorService'; import 'vs/workbench/services/editor/browser/editorResolverService'; +import 'vs/workbench/services/aiEmbeddingVector/common/aiEmbeddingVectorService'; +import 'vs/workbench/services/aiRelatedInformation/common/aiRelatedInformationService'; import 'vs/workbench/services/history/browser/historyService'; import 'vs/workbench/services/activity/browser/activityService'; import 'vs/workbench/services/keybinding/browser/keybindingService'; diff --git a/src/vscode-dts/vscode.proposed.aiRelatedInformation.d.ts b/src/vscode-dts/vscode.proposed.aiRelatedInformation.d.ts new file mode 100644 index 00000000000..d3916c50608 --- /dev/null +++ b/src/vscode-dts/vscode.proposed.aiRelatedInformation.d.ts @@ -0,0 +1,62 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +declare module 'vscode' { + + // https://github.com/microsoft/vscode/issues/190909 + + export interface SearchResult { + // from Andrea + preview: string; + resource: Uri; + location: Range; + } + + export enum RelatedInformationType { + SymbolInformation = 1, + CommandInformation = 2, + SearchInformation = 3, + SettingInformation = 4 + } + + export interface RelatedInformationResult { + type: RelatedInformationType; + weight: number; + } + + export interface SymbolInformationResult extends RelatedInformationResult { + type: RelatedInformationType.SymbolInformation; + symbolInformation: SymbolInformation; + } + + export interface CommandInformationResult extends RelatedInformationResult { + type: RelatedInformationType.CommandInformation; + command: string; + } + + export interface SettingInformationResult extends RelatedInformationResult { + type: RelatedInformationType.SettingInformation; + setting: string; + } + + export interface SearchInformationResult extends RelatedInformationResult { + type: RelatedInformationType.SearchInformation; + searchResult: SearchResult; + } + + export interface RelatedInformationProvider { + provideRelatedInformation(query: string, types: RelatedInformationType[], token: CancellationToken): ProviderResult; + } + + export interface EmbeddingVectorProvider { + provideEmbeddingVector(strings: string[], token: CancellationToken): ProviderResult; + } + + export namespace ai { + export function getRelatedInformation(query: string, types: RelatedInformationType[], token: CancellationToken): Thenable; + export function registerRelatedInformationProvider(types: RelatedInformationType[], provider: RelatedInformationProvider): Disposable; + export function registerEmbeddingVectorProvider(model: string, provider: EmbeddingVectorProvider): Disposable; + } +} From 08a8a80a265ce0f47cc97131d6466b31b14fb2a6 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 22 Aug 2023 21:48:10 +0200 Subject: [PATCH 093/221] debt - change `listenStream` to use a cancellation token (#191003) //cc @connor4312 --- src/vs/base/common/stream.ts | 14 ++++++-------- src/vs/base/test/common/stream.test.ts | 11 +++++++---- .../contrib/files/browser/fileImportExport.ts | 4 ++-- .../workbench/services/textfile/common/encoding.ts | 9 ++++++--- 4 files changed, 21 insertions(+), 17 deletions(-) diff --git a/src/vs/base/common/stream.ts b/src/vs/base/common/stream.ts index 9f1039c0e52..055558fc748 100644 --- a/src/vs/base/common/stream.ts +++ b/src/vs/base/common/stream.ts @@ -3,8 +3,9 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { CancellationToken } from 'vs/base/common/cancellation'; import { onUnexpectedError } from 'vs/base/common/errors'; -import { DisposableStore, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; +import { DisposableStore, toDisposable } from 'vs/base/common/lifecycle'; /** * The payload that flows in readable stream events. @@ -567,17 +568,16 @@ export interface IStreamListener { /** * Helper to listen to all events of a T stream in proper order. */ -export function listenStream(stream: ReadableStreamEvents, listener: IStreamListener): IDisposable { - let destroyed = false; +export function listenStream(stream: ReadableStreamEvents, listener: IStreamListener, token?: CancellationToken): void { stream.on('error', error => { - if (!destroyed) { + if (!token?.isCancellationRequested) { listener.onError(error); } }); stream.on('end', () => { - if (!destroyed) { + if (!token?.isCancellationRequested) { listener.onEnd(); } }); @@ -586,12 +586,10 @@ export function listenStream(stream: ReadableStreamEvents, listener: IStre // into flowing mode. As such it is important to // add this listener last (DO NOT CHANGE!) stream.on('data', data => { - if (!destroyed) { + if (!token?.isCancellationRequested) { listener.onData(data); } }); - - return toDisposable(() => destroyed = true); } /** diff --git a/src/vs/base/test/common/stream.test.ts b/src/vs/base/test/common/stream.test.ts index 78c38d691a4..63d30530a95 100644 --- a/src/vs/base/test/common/stream.test.ts +++ b/src/vs/base/test/common/stream.test.ts @@ -6,6 +6,7 @@ import * as assert from 'assert'; import { timeout } from 'vs/base/common/async'; import { bufferToReadable, VSBuffer } from 'vs/base/common/buffer'; +import { CancellationTokenSource } from 'vs/base/common/cancellation'; import { consumeReadable, consumeStream, isReadable, isReadableBufferedStream, isReadableStream, listenStream, newWriteableStream, peekReadable, peekStream, prefixedReadable, prefixedStream, Readable, ReadableStream, toReadable, toStream, transform } from 'vs/base/common/stream'; suite('Stream', () => { @@ -351,14 +352,16 @@ suite('Stream', () => { assert.strictEqual(end, true); }); - test('listenStream - dispose', () => { + test('listenStream - cancellation', () => { const stream = newWriteableStream(strings => strings.join()); let error = false; let end = false; let data = ''; - const disposable = listenStream(stream, { + const cts = new CancellationTokenSource(); + + listenStream(stream, { onData: d => { data = d; }, @@ -368,9 +371,9 @@ suite('Stream', () => { onEnd: () => { end = true; } - }); + }, cts.token); - disposable.dispose(); + cts.cancel(); stream.write('Hello'); assert.strictEqual(data, ''); diff --git a/src/vs/workbench/contrib/files/browser/fileImportExport.ts b/src/vs/workbench/contrib/files/browser/fileImportExport.ts index e93695b3c16..56c7149a0ae 100644 --- a/src/vs/workbench/contrib/files/browser/fileImportExport.ts +++ b/src/vs/workbench/contrib/files/browser/fileImportExport.ts @@ -715,7 +715,7 @@ export class FileDownload { reject(canceled()); })); - disposables.add(listenStream(sourceStream, { + listenStream(sourceStream, { onData: data => { target.write(data.buffer); this.reportProgress(contents.name, contents.size, data.byteLength, operation); @@ -728,7 +728,7 @@ export class FileDownload { disposables.dispose(); resolve(); } - })); + }, token); }); } diff --git a/src/vs/workbench/services/textfile/common/encoding.ts b/src/vs/workbench/services/textfile/common/encoding.ts index 6675f732b0e..ad67fb4f422 100644 --- a/src/vs/workbench/services/textfile/common/encoding.ts +++ b/src/vs/workbench/services/textfile/common/encoding.ts @@ -6,6 +6,7 @@ import { Readable, ReadableStream, newWriteableStream, listenStream } from 'vs/base/common/stream'; import { VSBuffer, VSBufferReadable, VSBufferReadableStream } from 'vs/base/common/buffer'; import { importAMDNodeModule } from 'vs/amdX'; +import { CancellationTokenSource } from 'vs/base/common/cancellation'; export const UTF8 = 'utf8'; export const UTF8_with_bom = 'utf8bom'; @@ -124,6 +125,8 @@ export function toDecodeStream(source: VSBufferReadableStream, options: IDecodeS let decoder: IDecoderStream | undefined = undefined; + const cts = new CancellationTokenSource(); + const createDecoder = async () => { try { @@ -158,14 +161,14 @@ export function toDecodeStream(source: VSBufferReadableStream, options: IDecodeS } catch (error) { // Stop handling anything from the source and target - sourceListener?.dispose(); + cts.cancel(); target.destroy(); reject(error); } }; - const sourceListener = listenStream(source, { + listenStream(source, { onData: async chunk => { // if the decoder is ready, we just write directly @@ -205,7 +208,7 @@ export function toDecodeStream(source: VSBufferReadableStream, options: IDecodeS // end the target with the remainders of the decoder target.end(decoder?.end()); } - }); + }, cts.token); }); } From bcea55affb1ccdc0b15fe39c86a79268c16dab72 Mon Sep 17 00:00:00 2001 From: Justin Chen <54879025+justschen@users.noreply.github.com> Date: Tue, 22 Aug 2023 12:57:54 -0700 Subject: [PATCH 094/221] fixes hover/click ui bug in #190508 (#191009) * bug fix for issue with hover/clicks * code cleanup, removing spaces --- src/vs/platform/actionWidget/browser/actionWidget.css | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vs/platform/actionWidget/browser/actionWidget.css b/src/vs/platform/actionWidget/browser/actionWidget.css index 1384b5f5e74..539af6ca265 100644 --- a/src/vs/platform/actionWidget/browser/actionWidget.css +++ b/src/vs/platform/actionWidget/browser/actionWidget.css @@ -94,7 +94,8 @@ .action-widget .monaco-list-row.action.option-disabled, .action-widget .monaco-list:focus .monaco-list-row.focused.action.option-disabled, -.action-widget .monaco-list-row.action.option-disabled .codicon { +.action-widget .monaco-list-row.action.option-disabled .codicon, +.action-widget .monaco-list:not(.drop-target):not(.dragging) .monaco-list-row:hover:not(.selected):not(.focused).option-disabled { color: var(--vscode-disabledForeground); } From f09b5e1c3a14e3b0a57ceffb6d42ee85993789b8 Mon Sep 17 00:00:00 2001 From: meganrogge Date: Tue, 22 Aug 2023 13:06:01 -0700 Subject: [PATCH 095/221] use store --- .../browser/textAreaSyncAddon.ts | 20 ++++++++----------- 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/textAreaSyncAddon.ts b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/textAreaSyncAddon.ts index 9a52fc9c00a..54599032dc5 100644 --- a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/textAreaSyncAddon.ts +++ b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/textAreaSyncAddon.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Disposable, MutableDisposable } from 'vs/base/common/lifecycle'; +import { Disposable, DisposableStore, MutableDisposable } from 'vs/base/common/lifecycle'; import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; import { ITerminalCapabilityStore, TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities'; import { ITerminalLogService } from 'vs/platform/terminal/common/terminal'; @@ -18,9 +18,7 @@ export interface ITextAreaData { export class TextAreaSyncAddon extends Disposable implements ITerminalAddon { private _terminal: Terminal | undefined; - private _onCursorMoveListener = this._register(new MutableDisposable()); - private _onDidFocusListener = this._register(new MutableDisposable()); - private _onKeyListener = this._register(new MutableDisposable()); + private _listeners = this._register(new MutableDisposable()); activate(terminal: Terminal): void { this._terminal = terminal; if (this._accessibilityService.isScreenReaderOptimized()) { @@ -40,22 +38,20 @@ export class TextAreaSyncAddon extends Disposable implements ITerminalAddon { this._refreshTextArea(); this._setListeners(); } else { - this._onCursorMoveListener.clear(); - this._onDidFocusListener.clear(); - this._onKeyListener.clear(); + this._listeners.clear(); } })); } private _setListeners(): void { if (this._accessibilityService.isScreenReaderOptimized() && this._terminal) { - this._onCursorMoveListener.value = this._terminal.onCursorMove(() => this._refreshTextArea()); - this._onDidFocusListener.value = this._onDidFocus(() => this._refreshTextArea()); - this._onKeyListener.value = this._terminal.onKey((e) => { + this._listeners.value?.add(this._terminal.onCursorMove(() => this._refreshTextArea())); + this._listeners.value?.add(this._onDidFocus(() => this._refreshTextArea())); + this._listeners.value?.add(this._terminal.onKey((e) => { if (e.domEvent.key === 'UpArrow') { this._refreshTextArea(); } - }); + })); } } @@ -113,7 +109,7 @@ export class TextAreaSyncAddon extends Disposable implements ITerminalAddon { this._logService.debug(`TextAreaSyncAddon#refreshTextArea: content is "${content}"`); this._logService.debug(`TextAreaSyncAddon#refreshTextArea: textContent is "${textArea.textContent}"`); if (content !== textArea.textContent) { - textArea.textContent = content.trim(); + textArea.textContent = content; this._logService.debug(`TextAreaSyncAddon#refreshTextArea: textContent changed to "${content}"`); } From c71d140106897d0225487c85d9e215d3fd8a06b3 Mon Sep 17 00:00:00 2001 From: meganrogge Date: Tue, 22 Aug 2023 13:13:34 -0700 Subject: [PATCH 096/221] create store --- .../accessibility/browser/textAreaSyncAddon.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/textAreaSyncAddon.ts b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/textAreaSyncAddon.ts index 54599032dc5..22df31960fd 100644 --- a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/textAreaSyncAddon.ts +++ b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/textAreaSyncAddon.ts @@ -10,6 +10,7 @@ import { ITerminalLogService } from 'vs/platform/terminal/common/terminal'; import type { Terminal, ITerminalAddon } from 'xterm'; import { Event } from 'vs/base/common/event'; import { ITerminalInstance } from 'vs/workbench/contrib/terminal/browser/terminal'; +import { debounce } from 'vs/base/common/decorators'; export interface ITextAreaData { content: string; @@ -45,9 +46,10 @@ export class TextAreaSyncAddon extends Disposable implements ITerminalAddon { private _setListeners(): void { if (this._accessibilityService.isScreenReaderOptimized() && this._terminal) { - this._listeners.value?.add(this._terminal.onCursorMove(() => this._refreshTextArea())); - this._listeners.value?.add(this._onDidFocus(() => this._refreshTextArea())); - this._listeners.value?.add(this._terminal.onKey((e) => { + this._listeners.value = new DisposableStore(); + this._listeners.value.add(this._terminal.onCursorMove(() => this._refreshTextArea())); + this._listeners.value.add(this._onDidFocus(() => this._refreshTextArea())); + this._listeners.value.add(this._terminal.onKey((e) => { if (e.domEvent.key === 'UpArrow') { this._refreshTextArea(); } @@ -55,6 +57,7 @@ export class TextAreaSyncAddon extends Disposable implements ITerminalAddon { } } + @debounce(50) private _refreshTextArea(): void { if (!this._terminal) { return; From da896a565443d795eb4cfd99708206af0461af16 Mon Sep 17 00:00:00 2001 From: meganrogge Date: Tue, 22 Aug 2023 13:17:23 -0700 Subject: [PATCH 097/221] add listener to textarea directly --- .../browser/terminal.accessibility.contribution.ts | 2 +- .../accessibility/browser/textAreaSyncAddon.ts | 8 +++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminal.accessibility.contribution.ts b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminal.accessibility.contribution.ts index 3594567f2b1..b69943c18de 100644 --- a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminal.accessibility.contribution.ts +++ b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminal.accessibility.contribution.ts @@ -40,7 +40,7 @@ class TextAreaSyncContribution extends DisposableStore implements ITerminalContr super(); } xtermReady(xterm: IXtermTerminal & { raw: Terminal }): void { - const addon = this._instantiationService.createInstance(TextAreaSyncAddon, this._instance.capabilities, this._instance.onDidFocus); + const addon = this._instantiationService.createInstance(TextAreaSyncAddon, this._instance.capabilities); xterm.raw.loadAddon(addon); addon.activate(xterm.raw); } diff --git a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/textAreaSyncAddon.ts b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/textAreaSyncAddon.ts index 22df31960fd..454820589ba 100644 --- a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/textAreaSyncAddon.ts +++ b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/textAreaSyncAddon.ts @@ -8,9 +8,8 @@ import { IAccessibilityService } from 'vs/platform/accessibility/common/accessib import { ITerminalCapabilityStore, TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities'; import { ITerminalLogService } from 'vs/platform/terminal/common/terminal'; import type { Terminal, ITerminalAddon } from 'xterm'; -import { Event } from 'vs/base/common/event'; -import { ITerminalInstance } from 'vs/workbench/contrib/terminal/browser/terminal'; import { debounce } from 'vs/base/common/decorators'; +import { addDisposableListener } from 'vs/base/browser/dom'; export interface ITextAreaData { content: string; @@ -29,7 +28,6 @@ export class TextAreaSyncAddon extends Disposable implements ITerminalAddon { constructor( private readonly _capabilities: ITerminalCapabilityStore, - private readonly _onDidFocus: Event, @IAccessibilityService private readonly _accessibilityService: IAccessibilityService, @ITerminalLogService private readonly _logService: ITerminalLogService ) { @@ -45,10 +43,10 @@ export class TextAreaSyncAddon extends Disposable implements ITerminalAddon { } private _setListeners(): void { - if (this._accessibilityService.isScreenReaderOptimized() && this._terminal) { + if (this._accessibilityService.isScreenReaderOptimized() && this._terminal?.textarea) { this._listeners.value = new DisposableStore(); this._listeners.value.add(this._terminal.onCursorMove(() => this._refreshTextArea())); - this._listeners.value.add(this._onDidFocus(() => this._refreshTextArea())); + this._listeners.value.add(addDisposableListener(this._terminal.textarea, 'focus', () => this._refreshTextArea())); this._listeners.value.add(this._terminal.onKey((e) => { if (e.domEvent.key === 'UpArrow') { this._refreshTextArea(); From b1d5542cfd04b251f3e26679c0954d45667034e7 Mon Sep 17 00:00:00 2001 From: Kartik Raj Date: Tue, 22 Aug 2023 20:22:32 +0000 Subject: [PATCH 098/221] Finalize proposed env workspace collection API --- extensions/vscode-api-tests/package.json | 1 - .../src/singlefolder-tests/terminal.test.ts | 5 +-- .../api/common/extHostTerminalService.ts | 4 -- .../common/extensionsApiProposals.ts | 1 - src/vscode-dts/vscode.d.ts | 31 ++++++++++++-- ...scode.proposed.envCollectionWorkspace.d.ts | 42 ------------------- 6 files changed, 30 insertions(+), 54 deletions(-) delete mode 100644 src/vscode-dts/vscode.proposed.envCollectionWorkspace.d.ts diff --git a/extensions/vscode-api-tests/package.json b/extensions/vscode-api-tests/package.json index 5ee95741ff0..911f7b746ac 100644 --- a/extensions/vscode-api-tests/package.json +++ b/extensions/vscode-api-tests/package.json @@ -51,7 +51,6 @@ "telemetry", "windowActivity", "interactiveUserActions", - "envCollectionWorkspace", "envCollectionOptions" ], "private": true, diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/terminal.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/terminal.test.ts index 76408d2de77..4275898e244 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/terminal.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/terminal.test.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { deepStrictEqual, doesNotThrow, equal, ok, strictEqual, throws } from 'assert'; -import { commands, ConfigurationTarget, Disposable, env, EnvironmentVariableMutator, EnvironmentVariableMutatorOptions, EnvironmentVariableMutatorType, EventEmitter, ExtensionContext, extensions, ExtensionTerminalOptions, GlobalEnvironmentVariableCollection, Pseudoterminal, Terminal, TerminalDimensions, TerminalExitReason, TerminalOptions, TerminalState, UIKind, Uri, window, workspace } from 'vscode'; +import { commands, ConfigurationTarget, Disposable, env, EnvironmentVariableMutator, EnvironmentVariableMutatorOptions, EnvironmentVariableMutatorType, EventEmitter, ExtensionContext, extensions, ExtensionTerminalOptions, Pseudoterminal, Terminal, TerminalDimensions, TerminalExitReason, TerminalOptions, TerminalState, UIKind, Uri, window, workspace } from 'vscode'; import { assertNoRpc, poll } from '../utils'; // Disable terminal tests: @@ -912,8 +912,7 @@ import { assertNoRpc, poll } from '../utils'; }); test('get and forEach should work (scope)', () => { - // TODO: Remove cast once `envCollectionWorkspace` API is finalized. - const collection = extensionContext.environmentVariableCollection as GlobalEnvironmentVariableCollection; + const collection = extensionContext.environmentVariableCollection; disposables.push({ dispose: () => collection.clear() }); const scope = { workspaceFolder: { uri: Uri.file('workspace1'), name: 'workspace1', index: 0 } }; const scopedCollection = collection.getScoped(scope); diff --git a/src/vs/workbench/api/common/extHostTerminalService.ts b/src/vs/workbench/api/common/extHostTerminalService.ts index c7d8b2a83d0..84f2cac70c1 100644 --- a/src/vs/workbench/api/common/extHostTerminalService.ts +++ b/src/vs/workbench/api/common/extHostTerminalService.ts @@ -929,10 +929,6 @@ class UnifiedEnvironmentVariableCollection { } getScopedEnvironmentVariableCollection(scope: vscode.EnvironmentVariableScope | undefined): IEnvironmentVariableCollection { - if (this._extension && scope) { - // TODO: This should be removed when the env var extension API(s) are stabilized - checkProposedApiEnabled(this._extension, 'envCollectionWorkspace'); - } const scopedCollectionKey = this.getScopeKey(scope); let scopedCollection = this.scopedCollections.get(scopedCollectionKey); if (!scopedCollection) { diff --git a/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts b/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts index 8b1cba0367d..336fc0caf50 100644 --- a/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts +++ b/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts @@ -41,7 +41,6 @@ export const allApiProposals = Object.freeze({ editSessionIdentityProvider: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.editSessionIdentityProvider.d.ts', editorInsets: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.editorInsets.d.ts', envCollectionOptions: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.envCollectionOptions.d.ts', - envCollectionWorkspace: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.envCollectionWorkspace.d.ts', envShellEvent: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.envShellEvent.d.ts', extensionRuntime: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.extensionRuntime.d.ts', extensionsAny: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.extensionsAny.d.ts', diff --git a/src/vscode-dts/vscode.d.ts b/src/vscode-dts/vscode.d.ts index db7d29f3b1b..8821ce6086c 100644 --- a/src/vscode-dts/vscode.d.ts +++ b/src/vscode-dts/vscode.d.ts @@ -7185,10 +7185,10 @@ declare module 'vscode' { readonly extensionPath: string; /** - * Gets the extension's environment variable collection for this workspace, enabling changes - * to be applied to terminal environment variables. + * Gets the extension's global environment variable collection for this workspace, enabling changes to be + * applied to terminal environment variables. */ - readonly environmentVariableCollection: EnvironmentVariableCollection; + readonly environmentVariableCollection: GlobalEnvironmentVariableCollection; /** * Get the absolute path of a resource contained in the extension. @@ -11429,6 +11429,31 @@ declare module 'vscode' { clear(): void; } + export interface GlobalEnvironmentVariableCollection extends EnvironmentVariableCollection { + /** + * Gets scope-specific environment variable collection for the extension. This enables alterations to + * terminal environment variables solely within the designated scope, and is applied in addition to (and + * after) the global collection. + * + * Each object obtained through this method is isolated and does not impact objects for other scopes, + * including the global collection. + * + * @param scope The scope to which the environment variable collection applies to. + * + * If a scope parameter is omitted, collection applicable to all relevant scopes for that parameter is + * returned. For instance, if the 'workspaceFolder' parameter is not specified, the collection that applies + * across all workspace folders will be returned. + */ + getScoped(scope: EnvironmentVariableScope): EnvironmentVariableCollection; + } + + export type EnvironmentVariableScope = { + /** + * Any specific workspace folder to get collection for. If unspecified, collection applicable to all workspace folders is returned. + */ + workspaceFolder?: WorkspaceFolder; + }; + /** * A location in the editor at which progress information can be shown. It depends on the * location how progress is visually represented. diff --git a/src/vscode-dts/vscode.proposed.envCollectionWorkspace.d.ts b/src/vscode-dts/vscode.proposed.envCollectionWorkspace.d.ts deleted file mode 100644 index fb4b78e172b..00000000000 --- a/src/vscode-dts/vscode.proposed.envCollectionWorkspace.d.ts +++ /dev/null @@ -1,42 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -declare module 'vscode' { - - // https://github.com/microsoft/vscode/issues/171173 - - // export interface ExtensionContext { - // /** - // * Gets the extension's global environment variable collection for this workspace, enabling changes to be - // * applied to terminal environment variables. - // */ - // readonly environmentVariableCollection: GlobalEnvironmentVariableCollection; - // } - - export interface GlobalEnvironmentVariableCollection extends EnvironmentVariableCollection { - /** - * Gets scope-specific environment variable collection for the extension. This enables alterations to - * terminal environment variables solely within the designated scope, and is applied in addition to (and - * after) the global collection. - * - * Each object obtained through this method is isolated and does not impact objects for other scopes, - * including the global collection. - * - * @param scope The scope to which the environment variable collection applies to. - * - * If a scope parameter is omitted, collection applicable to all relevant scopes for that parameter is - * returned. For instance, if the 'workspaceFolder' parameter is not specified, the collection that applies - * across all workspace folders will be returned. - */ - getScoped(scope: EnvironmentVariableScope): EnvironmentVariableCollection; - } - - export type EnvironmentVariableScope = { - /** - * Any specific workspace folder to get collection for. If unspecified, collection applicable to all workspace folders is returned. - */ - workspaceFolder?: WorkspaceFolder; - }; -} From d94db47be294698220a2598e639aba31babffb20 Mon Sep 17 00:00:00 2001 From: Peng Lyu Date: Tue, 22 Aug 2023 13:32:14 -0700 Subject: [PATCH 099/221] Capitalize transpose command (#191011) --- .../editor/contrib/linesOperations/browser/linesOperations.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/editor/contrib/linesOperations/browser/linesOperations.ts b/src/vs/editor/contrib/linesOperations/browser/linesOperations.ts index 0e3355907af..11a5c6c4f27 100644 --- a/src/vs/editor/contrib/linesOperations/browser/linesOperations.ts +++ b/src/vs/editor/contrib/linesOperations/browser/linesOperations.ts @@ -953,8 +953,8 @@ export class TransposeAction extends EditorAction { constructor() { super({ id: 'editor.action.transpose', - label: nls.localize('editor.transpose', "Transpose characters around the cursor"), - alias: 'Transpose characters around the cursor', + label: nls.localize('editor.transpose', "Transpose Characters around the Cursor"), + alias: 'Transpose Characters around the Cursor', precondition: EditorContextKeys.writable }); } From 7f459649e4ed959cc067374aefca6f10172c45c6 Mon Sep 17 00:00:00 2001 From: meganrogge Date: Tue, 22 Aug 2023 13:56:58 -0700 Subject: [PATCH 100/221] get it to work via value instead of textContent --- .../accessibility/browser/textAreaSyncAddon.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/textAreaSyncAddon.ts b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/textAreaSyncAddon.ts index 454820589ba..3251695238b 100644 --- a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/textAreaSyncAddon.ts +++ b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/textAreaSyncAddon.ts @@ -91,7 +91,7 @@ export class TextAreaSyncAddon extends Disposable implements ITerminalAddon { this._logService.debug(`TextAreaSyncAddon#refreshTextArea: no content`); const textArea = this._terminal.textarea; if (textArea) { - textArea.textContent = ''; + textArea.value = ''; } return; } @@ -110,7 +110,7 @@ export class TextAreaSyncAddon extends Disposable implements ITerminalAddon { this._logService.debug(`TextAreaSyncAddon#refreshTextArea: content is "${content}"`); this._logService.debug(`TextAreaSyncAddon#refreshTextArea: textContent is "${textArea.textContent}"`); if (content !== textArea.textContent) { - textArea.textContent = content; + textArea.value = content; this._logService.debug(`TextAreaSyncAddon#refreshTextArea: textContent changed to "${content}"`); } @@ -122,6 +122,5 @@ export class TextAreaSyncAddon extends Disposable implements ITerminalAddon { textArea.selectionEnd = cursorX; this._logService.debug(`TextAreaSyncAddon#refreshTextArea: selectionStart changed to ${cursorX}`); } - // TODO: cursorY? } } From 0b13f1859caf75a2d3d16a29afcbef03e111447b Mon Sep 17 00:00:00 2001 From: Tyler James Leonhardt Date: Tue, 22 Aug 2023 14:03:06 -0700 Subject: [PATCH 101/221] Update Settings to use AiRelatedInformation (#191017) ref #190909 --- .../preferences/browser/preferencesSearch.ts | 60 ++++++++++++++++--- .../common/aiRelatedInformation.ts | 5 ++ .../common/semanticSimilarityService.ts | 6 ++ 3 files changed, 63 insertions(+), 8 deletions(-) diff --git a/src/vs/workbench/contrib/preferences/browser/preferencesSearch.ts b/src/vs/workbench/contrib/preferences/browser/preferencesSearch.ts index 486c29e09be..fe7ce4b6848 100644 --- a/src/vs/workbench/contrib/preferences/browser/preferencesSearch.ts +++ b/src/vs/workbench/contrib/preferences/browser/preferencesSearch.ts @@ -21,6 +21,7 @@ import { ExtensionType } from 'vs/platform/extensions/common/extensions'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { ISemanticSimilarityService } from 'vs/workbench/services/semanticSimilarity/common/semanticSimilarityService'; +import { IAiRelatedInformationService, RelatedInformationType, SettingInformationResult } from 'vs/workbench/services/aiRelatedInformation/common/aiRelatedInformation'; export interface IEndpointDetails { urlBase?: string; @@ -302,8 +303,10 @@ class RemoteSearchKeysProvider { private settingsRecord: Record = {}; private currentPreferencesModel: ISettingsEditorModel | undefined; - constructor(private readonly semanticSimilarityService: ISemanticSimilarityService) { - } + constructor( + private readonly aiRelatedInformationService: IAiRelatedInformationService, + private readonly semanticSimilarityService: ISemanticSimilarityService + ) { } updateModel(preferencesModel: ISettingsEditorModel) { if (preferencesModel === this.currentPreferencesModel) { @@ -318,7 +321,10 @@ class RemoteSearchKeysProvider { this.settingKeys = []; this.settingsRecord = {}; - if (!this.semanticSimilarityService.isEnabled() || !this.currentPreferencesModel) { + if ( + !this.currentPreferencesModel || + (!this.semanticSimilarityService.isEnabled() && !this.aiRelatedInformationService.isEnabled()) + ) { return; } @@ -353,8 +359,9 @@ export class RemoteSearchProvider implements ISearchProvider { constructor( @ISemanticSimilarityService private readonly semanticSimilarityService: ISemanticSimilarityService, + @IAiRelatedInformationService private readonly aiRelatedInformationService: IAiRelatedInformationService ) { - this._keysProvider = new RemoteSearchKeysProvider(semanticSimilarityService); + this._keysProvider = new RemoteSearchKeysProvider(aiRelatedInformationService, semanticSimilarityService); } setFilter(filter: string) { @@ -362,11 +369,26 @@ export class RemoteSearchProvider implements ISearchProvider { } async searchModel(preferencesModel: ISettingsEditorModel, token?: CancellationToken | undefined): Promise { - if (!this.semanticSimilarityService.isEnabled() || !this._filter) { + if ( + !this._filter || + (!this.semanticSimilarityService.isEnabled() && !this.aiRelatedInformationService.isEnabled())) { return null; } this._keysProvider.updateModel(preferencesModel); + const filterMatches = this.aiRelatedInformationService.isEnabled() + ? await this.getAiRelatedInformationItems(token) + : this.semanticSimilarityService.isEnabled() + ? await this.getSemanticSimilarityItems(token) + : []; + + return { + filterMatches + }; + } + + // TODO: Remove this when all semantic similarity providers are migrated to aiRelatedInformationService + private async getSemanticSimilarityItems(token?: CancellationToken | undefined) { const settingKeys = this._keysProvider.getSettingKeys(); const settingsRecord = this._keysProvider.getSettingsRecord(); @@ -389,9 +411,31 @@ export class RemoteSearchProvider implements ISearchProvider { }); numOfSmartPicks++; } - return { - filterMatches - }; + + return filterMatches; + } + + private async getAiRelatedInformationItems(token?: CancellationToken | undefined) { + const settingsRecord = this._keysProvider.getSettingsRecord(); + + const filterMatches: ISettingMatch[] = []; + const relatedInformation = await this.aiRelatedInformationService.getRelatedInformation(this._filter, [RelatedInformationType.SettingInformation], token ?? CancellationToken.None) as SettingInformationResult[]; + relatedInformation.sort((a, b) => b.weight - a.weight); + + for (const info of relatedInformation) { + if (info.weight < RemoteSearchProvider.SEMANTIC_SIMILARITY_THRESHOLD || filterMatches.length === RemoteSearchProvider.SEMANTIC_SIMILARITY_MAX_PICKS) { + break; + } + const pick = info.setting; + filterMatches.push({ + setting: settingsRecord[pick], + matches: [settingsRecord[pick].range], + matchType: SettingMatchType.RemoteMatch, + score: info.weight + }); + } + + return filterMatches; } } diff --git a/src/vs/workbench/services/aiRelatedInformation/common/aiRelatedInformation.ts b/src/vs/workbench/services/aiRelatedInformation/common/aiRelatedInformation.ts index 75248fb38d5..a8bddf2c1e4 100644 --- a/src/vs/workbench/services/aiRelatedInformation/common/aiRelatedInformation.ts +++ b/src/vs/workbench/services/aiRelatedInformation/common/aiRelatedInformation.ts @@ -26,6 +26,11 @@ export interface CommandInformationResult extends RelatedInformationResult { command: string; } +export interface SettingInformationResult extends RelatedInformationResult { + type: RelatedInformationType.SettingInformation; + setting: string; +} + export interface IAiRelatedInformationService { readonly _serviceBrand: undefined; diff --git a/src/vs/workbench/services/semanticSimilarity/common/semanticSimilarityService.ts b/src/vs/workbench/services/semanticSimilarity/common/semanticSimilarityService.ts index ff203430c99..e322503d117 100644 --- a/src/vs/workbench/services/semanticSimilarity/common/semanticSimilarityService.ts +++ b/src/vs/workbench/services/semanticSimilarity/common/semanticSimilarityService.ts @@ -11,8 +11,14 @@ import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/ import { StopWatch } from 'vs/base/common/stopwatch'; import { ILogService } from 'vs/platform/log/common/log'; +/** + * @deprecated Use `IAiRelatedInformationService` instead. + */ export const ISemanticSimilarityService = createDecorator('ISemanticSimilarityService'); +/** + * @deprecated Use `IAiRelatedInformationService` instead. + */ export interface ISemanticSimilarityService { readonly _serviceBrand: undefined; From 252a9df9b5a90aaf7b7a58deb458fece45c083d1 Mon Sep 17 00:00:00 2001 From: Kartik Raj Date: Tue, 22 Aug 2023 21:08:09 +0000 Subject: [PATCH 102/221] Remove unnecessay doc --- src/vscode-dts/vscode.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vscode-dts/vscode.d.ts b/src/vscode-dts/vscode.d.ts index 8821ce6086c..aafc71211e2 100644 --- a/src/vscode-dts/vscode.d.ts +++ b/src/vscode-dts/vscode.d.ts @@ -11449,7 +11449,7 @@ declare module 'vscode' { export type EnvironmentVariableScope = { /** - * Any specific workspace folder to get collection for. If unspecified, collection applicable to all workspace folders is returned. + * Any specific workspace folder to get collection for. */ workspaceFolder?: WorkspaceFolder; }; From cbc1cba21b6e288c3d5e976853cc34c6335581fb Mon Sep 17 00:00:00 2001 From: meganrogge Date: Tue, 22 Aug 2023 14:09:11 -0700 Subject: [PATCH 103/221] use better event, fix bug --- .../accessibility/browser/textAreaSyncAddon.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/textAreaSyncAddon.ts b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/textAreaSyncAddon.ts index 3251695238b..b914a3e65d9 100644 --- a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/textAreaSyncAddon.ts +++ b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/textAreaSyncAddon.ts @@ -47,11 +47,7 @@ export class TextAreaSyncAddon extends Disposable implements ITerminalAddon { this._listeners.value = new DisposableStore(); this._listeners.value.add(this._terminal.onCursorMove(() => this._refreshTextArea())); this._listeners.value.add(addDisposableListener(this._terminal.textarea, 'focus', () => this._refreshTextArea())); - this._listeners.value.add(this._terminal.onKey((e) => { - if (e.domEvent.key === 'UpArrow') { - this._refreshTextArea(); - } - })); + this._listeners.value.add(this._terminal.onData((e) => this._refreshTextArea())); } } From 013600cf334f804298647fa0ab8a8dde99925596 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 22 Aug 2023 14:14:24 -0700 Subject: [PATCH 104/221] Don't show `copy image` in command palette (#190907) #190773 --- extensions/markdown-language-features/package.json | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/extensions/markdown-language-features/package.json b/extensions/markdown-language-features/package.json index 60e80b169d3..78c71ce9138 100644 --- a/extensions/markdown-language-features/package.json +++ b/extensions/markdown-language-features/package.json @@ -123,7 +123,8 @@ "commands": [ { "command": "_markdown.copyImage", - "title": "%markdown.copyImage.title%" + "title": "%markdown.copyImage.title%", + "category": "Markdown" }, { "command": "markdown.showPreview", @@ -244,6 +245,10 @@ } ], "commandPalette": [ + { + "command": "_markdown.copyImage", + "when": "false" + }, { "command": "markdown.showPreview", "when": "editorLangId == markdown && !notebookEditorFocused", From b9e61998f8ead7f934491b0d844cc18f8693f71c Mon Sep 17 00:00:00 2001 From: meganrogge Date: Tue, 22 Aug 2023 14:36:20 -0700 Subject: [PATCH 105/221] clean up --- .../browser/textAreaSyncAddon.ts | 113 ++++++++---------- 1 file changed, 52 insertions(+), 61 deletions(-) diff --git a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/textAreaSyncAddon.ts b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/textAreaSyncAddon.ts index b914a3e65d9..c4171b11aa2 100644 --- a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/textAreaSyncAddon.ts +++ b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/textAreaSyncAddon.ts @@ -19,6 +19,9 @@ export interface ITextAreaData { export class TextAreaSyncAddon extends Disposable implements ITerminalAddon { private _terminal: Terminal | undefined; private _listeners = this._register(new MutableDisposable()); + private _currentCommand: string | undefined; + private _cursorX: number | undefined; + activate(terminal: Terminal): void { this._terminal = terminal; if (this._accessibilityService.isScreenReaderOptimized()) { @@ -34,7 +37,7 @@ export class TextAreaSyncAddon extends Disposable implements ITerminalAddon { super(); this._register(this._accessibilityService.onDidChangeScreenReaderOptimized(() => { if (this._accessibilityService.isScreenReaderOptimized()) { - this._refreshTextArea(); + this._syncTextArea(); this._setListeners(); } else { this._listeners.clear(); @@ -45,78 +48,66 @@ export class TextAreaSyncAddon extends Disposable implements ITerminalAddon { private _setListeners(): void { if (this._accessibilityService.isScreenReaderOptimized() && this._terminal?.textarea) { this._listeners.value = new DisposableStore(); - this._listeners.value.add(this._terminal.onCursorMove(() => this._refreshTextArea())); - this._listeners.value.add(addDisposableListener(this._terminal.textarea, 'focus', () => this._refreshTextArea())); - this._listeners.value.add(this._terminal.onData((e) => this._refreshTextArea())); + this._listeners.value.add(this._terminal.onCursorMove(() => this._syncTextArea())); + this._listeners.value.add(addDisposableListener(this._terminal.textarea, 'focus', () => this._syncTextArea())); + this._listeners.value.add(this._terminal.onData((e) => this._syncTextArea())); } } @debounce(50) - private _refreshTextArea(): void { - if (!this._terminal) { - return; - } + private _syncTextArea(): void { this._logService.debug('TextAreaSyncAddon#refreshTextArea'); - const commandCapability = this._capabilities.get(TerminalCapability.CommandDetection); - const currentCommand = commandCapability?.currentCommand; - if (!currentCommand) { - this._logService.debug(`TextAreaSyncAddon#refreshTextArea: no currentCommand`); - return; - } - const buffer = this._terminal.buffer.active; - const line = buffer.getLine(buffer.cursorY)?.translateToString(true); - let commandStartX: number | undefined; - if (!line) { - this._logService.debug(`TextAreaSyncAddon#refreshTextArea: no line`); - return; - } - let content: string | undefined; - if (currentCommand.commandStartX !== undefined) { - // Left prompt - content = line.substring(currentCommand.commandStartX); - commandStartX = currentCommand.commandStartX; - } else if (currentCommand.commandRightPromptStartX !== undefined) { - // Right prompt - content = line.substring(0, currentCommand.commandRightPromptStartX); - commandStartX = 0; - } else { - this._logService.debug(`TextAreaSyncAddon#refreshTextArea: no commandStartX or commandRightPromptStartX`); - } - - if (!content) { - this._logService.debug(`TextAreaSyncAddon#refreshTextArea: no content`); - const textArea = this._terminal.textarea; - if (textArea) { - textArea.value = ''; - } - return; - } - - if (commandStartX === undefined) { - this._logService.debug(`TextAreaSyncAddon#refreshTextArea: no commandStartX`); - return; - } - - const textArea = this._terminal.textarea; + const textArea = this._terminal?.textarea; if (!textArea) { this._logService.debug(`TextAreaSyncAddon#refreshTextArea: no textarea`); return; } - this._logService.debug(`TextAreaSyncAddon#refreshTextArea: content is "${content}"`); - this._logService.debug(`TextAreaSyncAddon#refreshTextArea: textContent is "${textArea.textContent}"`); - if (content !== textArea.textContent) { - textArea.value = content; - this._logService.debug(`TextAreaSyncAddon#refreshTextArea: textContent changed to "${content}"`); + this._updateCommandAndCursor(); + + if (this._currentCommand !== textArea.value) { + textArea.value = this._currentCommand || ''; + this._logService.debug(`TextAreaSyncAddon#refreshTextArea: text changed to "${this._currentCommand}"`); + } else if (!this._currentCommand) { + textArea.value = ''; + this._logService.debug(`TextAreaSyncAddon#refreshTextArea: text cleared`); } - const cursorX = buffer.cursorX - commandStartX; - this._logService.debug(`TextAreaSyncAddon#refreshTextArea: cursorX is ${cursorX}`); - this._logService.debug(`TextAreaSyncAddon#refreshTextArea: selectionStart is ${textArea.selectionStart}`); - if (cursorX !== textArea.selectionStart) { - textArea.selectionStart = cursorX; - textArea.selectionEnd = cursorX; - this._logService.debug(`TextAreaSyncAddon#refreshTextArea: selectionStart changed to ${cursorX}`); + if (this._cursorX !== textArea.selectionStart) { + textArea.selectionStart = this._cursorX ?? 0; + textArea.selectionEnd = this._cursorX ?? 0; + this._logService.debug(`TextAreaSyncAddon#refreshTextArea: selection start/end changed to ${this._cursorX}`); + } + } + + private _updateCommandAndCursor(): void { + if (!this._terminal) { + return; + } + const commandCapability = this._capabilities.get(TerminalCapability.CommandDetection); + const currentCommand = commandCapability?.currentCommand; + if (!currentCommand) { + this._logService.debug(`TextAreaSyncAddon#updateCommandAndCursor: no current command`); + return; + } + const buffer = this._terminal.buffer.active; + const line = buffer.getLine(buffer.cursorY)?.translateToString(true); + if (!line) { + this._logService.debug(`TextAreaSyncAddon#updateCommandAndCursor: no line`); + return; + } + if (currentCommand.commandStartX !== undefined) { + // Left prompt + this._currentCommand = line.substring(currentCommand.commandStartX); + this._cursorX = buffer.cursorX - currentCommand.commandStartX; + } else if (currentCommand.commandRightPromptStartX !== undefined) { + // Right prompt + this._currentCommand = line.substring(0, currentCommand.commandRightPromptStartX); + this._cursorX = buffer.cursorX; + } else { + this._currentCommand = undefined; + this._cursorX = undefined; + this._logService.debug(`TextAreaSyncAddon#updateCommandAndCursor: neither commandStartX nor commandRightPromptStartX`); } } } From bb2964c3be29ab03734ff649ef30dd6fe7430752 Mon Sep 17 00:00:00 2001 From: meganrogge Date: Tue, 22 Aug 2023 14:38:45 -0700 Subject: [PATCH 106/221] change names --- .../accessibility/browser/textAreaSyncAddon.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/textAreaSyncAddon.ts b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/textAreaSyncAddon.ts index c4171b11aa2..666f27389d9 100644 --- a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/textAreaSyncAddon.ts +++ b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/textAreaSyncAddon.ts @@ -25,7 +25,7 @@ export class TextAreaSyncAddon extends Disposable implements ITerminalAddon { activate(terminal: Terminal): void { this._terminal = terminal; if (this._accessibilityService.isScreenReaderOptimized()) { - this._setListeners(); + this._registerSyncListeners(); } } @@ -38,28 +38,28 @@ export class TextAreaSyncAddon extends Disposable implements ITerminalAddon { this._register(this._accessibilityService.onDidChangeScreenReaderOptimized(() => { if (this._accessibilityService.isScreenReaderOptimized()) { this._syncTextArea(); - this._setListeners(); + this._registerSyncListeners(); } else { this._listeners.clear(); } })); } - private _setListeners(): void { + private _registerSyncListeners(): void { if (this._accessibilityService.isScreenReaderOptimized() && this._terminal?.textarea) { this._listeners.value = new DisposableStore(); this._listeners.value.add(this._terminal.onCursorMove(() => this._syncTextArea())); + this._listeners.value.add(this._terminal.onData(() => this._syncTextArea())); this._listeners.value.add(addDisposableListener(this._terminal.textarea, 'focus', () => this._syncTextArea())); - this._listeners.value.add(this._terminal.onData((e) => this._syncTextArea())); } } @debounce(50) private _syncTextArea(): void { - this._logService.debug('TextAreaSyncAddon#refreshTextArea'); + this._logService.debug('TextAreaSyncAddon#syncTextArea'); const textArea = this._terminal?.textarea; if (!textArea) { - this._logService.debug(`TextAreaSyncAddon#refreshTextArea: no textarea`); + this._logService.debug(`TextAreaSyncAddon#syncTextArea: no textarea`); return; } @@ -67,16 +67,16 @@ export class TextAreaSyncAddon extends Disposable implements ITerminalAddon { if (this._currentCommand !== textArea.value) { textArea.value = this._currentCommand || ''; - this._logService.debug(`TextAreaSyncAddon#refreshTextArea: text changed to "${this._currentCommand}"`); + this._logService.debug(`TextAreaSyncAddon#syncTextArea: text changed to "${this._currentCommand}"`); } else if (!this._currentCommand) { textArea.value = ''; - this._logService.debug(`TextAreaSyncAddon#refreshTextArea: text cleared`); + this._logService.debug(`TextAreaSyncAddon#syncTextArea: text cleared`); } if (this._cursorX !== textArea.selectionStart) { textArea.selectionStart = this._cursorX ?? 0; textArea.selectionEnd = this._cursorX ?? 0; - this._logService.debug(`TextAreaSyncAddon#refreshTextArea: selection start/end changed to ${this._cursorX}`); + this._logService.debug(`TextAreaSyncAddon#syncTextArea: selection start/end changed to ${this._cursorX}`); } } From 870d659ffd7abc1ba47233888b82fdd180591db5 Mon Sep 17 00:00:00 2001 From: hsfzxjy Date: Wed, 23 Aug 2023 06:24:53 +0800 Subject: [PATCH 107/221] Fix nested list style in Markdown preview (#190936) --- .../markdown-language-features/media/markdown.css | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/extensions/markdown-language-features/media/markdown.css b/extensions/markdown-language-features/media/markdown.css index 939eafc442b..dba6176ffda 100644 --- a/extensions/markdown-language-features/media/markdown.css +++ b/extensions/markdown-language-features/media/markdown.css @@ -106,10 +106,10 @@ sup { line-height: 0; } -ul ul, -ul ol, -ol ul, -ol ol { +ul ul:first-child, +ul ol:first-child, +ol ul:first-child, +ol ol:first-child { margin-bottom: 0; } @@ -138,6 +138,10 @@ p { margin-bottom: 16px; } +li p { + margin-bottom: 0.7em; +} + ul, ol { margin-bottom: 0.7em; From 27907b6b7daf86ed03ea69b0bac745256a4c22b2 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 23 Aug 2023 00:27:49 +0200 Subject: [PATCH 108/221] Debt: remove no more needed EOL notifications for unsupported OS (fix #190680) (#191004) --- src/vs/workbench/electron-sandbox/window.ts | 137 ++++---------------- 1 file changed, 27 insertions(+), 110 deletions(-) diff --git a/src/vs/workbench/electron-sandbox/window.ts b/src/vs/workbench/electron-sandbox/window.ts index 5b625c9c856..1efcf6ba71f 100644 --- a/src/vs/workbench/electron-sandbox/window.ts +++ b/src/vs/workbench/electron-sandbox/window.ts @@ -723,118 +723,35 @@ export class NativeWindow extends Disposable { } } - // Windows 7/8/8.1 warning - if (isWindows) { - const version = this.environmentService.os.release.split('.'); - const majorVersion = version[0]; - const minorVersion = version[1]; - const eolReleases = new Map>([ - ['6', new Map([ - ['1', 'Windows 7 / Windows Server 2008 R2'], - ['2', 'Windows 8 / Windows Server 2012'], - ['3', 'Windows 8.1 / Windows Server 2012 R2'], - ])], - ]); + // Windows 32-bit warning + if (isWindows && this.environmentService.os.arch === 'ia32') { + const message = localize('windows32eolmessage', "{0} on Windows 32-bit will soon stop receiving updates. Consider upgrading to the 64-bit build.", this.productService.nameLong); + const actions = [{ + label: localize('windowseolBannerLearnMore', "Learn More"), + href: 'https://aka.ms/vscode-faq-old-windows' + }]; - // Refs https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-osversioninfoa - if (eolReleases.get(majorVersion)?.has(minorVersion)) { - const message = localize('windowseolmessage', "{0} on {1} will soon stop receiving updates. Consider upgrading your windows version.", this.productService.nameLong, eolReleases.get(majorVersion)?.get(minorVersion)); - const actions = [{ - label: localize('windowseolBannerLearnMore', "Learn More"), - href: 'https://aka.ms/vscode-faq-old-windows' - }]; + this.bannerService.show({ + id: 'windows32eol.banner', + message, + ariaLabel: localize('windowseolarialabel', "{0}. Use navigation keys to access banner actions.", message), + actions, + icon: Codicon.warning + }); - this.bannerService.show({ - id: 'windowseol.banner', - message, - ariaLabel: localize('windowseolarialabel', "{0}. Use navigation keys to access banner actions.", message), - actions, - icon: Codicon.warning - }); - - this.notificationService.prompt( - Severity.Warning, - message, - [{ - label: localize('learnMore', "Learn More"), - run: () => this.openerService.open(URI.parse('https://aka.ms/vscode-faq-old-windows')) - }], - { - neverShowAgain: { id: 'windowseol', isSecondary: true, scope: NeverShowAgainScope.APPLICATION }, - priority: NotificationPriority.URGENT, - sticky: true - } - ); - } - - else if (this.environmentService.os.arch === 'ia32') { - const message = localize('windows32eolmessage', "{0} on Windows 32-bit will soon stop receiving updates. Consider upgrading to the 64-bit build.", this.productService.nameLong); - const actions = [{ - label: localize('windowseolBannerLearnMore', "Learn More"), - href: 'https://aka.ms/vscode-faq-old-windows' - }]; - - this.bannerService.show({ - id: 'windows32eol.banner', - message, - ariaLabel: localize('windowseolarialabel', "{0}. Use navigation keys to access banner actions.", message), - actions, - icon: Codicon.warning - }); - - this.notificationService.prompt( - Severity.Warning, - message, - [{ - label: localize('learnMore', "Learn More"), - run: () => this.openerService.open(URI.parse('https://aka.ms/vscode-faq-old-windows')) - }], - { - neverShowAgain: { id: 'windows32eol', isSecondary: true, scope: NeverShowAgainScope.APPLICATION }, - priority: NotificationPriority.URGENT, - sticky: true - } - ); - } - } - - // MacOS 10.11 and 10.12 warning - if (isMacintosh) { - const majorVersion = this.environmentService.os.release.split('.')[0]; - const eolReleases = new Map([ - ['15', 'OS X El Capitan'], - ['16', 'macOS Sierra'], - ]); - // Refs https://en.wikipedia.org/wiki/Darwin_%28operating_system%29#Release_history - if (eolReleases.has(majorVersion)) { - const message = localize('macoseolmessage', "{0} on {1} will soon stop receiving updates. Consider upgrading your macOS version.", this.productService.nameLong, eolReleases.get(majorVersion)); - const actions = [{ - label: localize('macoseolBannerLearnMore', "Learn More"), - href: 'https://aka.ms/vscode-faq-old-macOS' - }]; - - this.bannerService.show({ - id: 'macoseol.banner', - message, - ariaLabel: localize('macoseolarialabel', "{0}. Use navigation keys to access banner actions.", message), - actions, - icon: Codicon.warning - }); - - this.notificationService.prompt( - Severity.Warning, - message, - [{ - label: localize('learnMore', "Learn More"), - run: () => this.openerService.open(URI.parse('https://aka.ms/vscode-faq-old-macOS')) - }], - { - neverShowAgain: { id: 'macoseol', isSecondary: true, scope: NeverShowAgainScope.APPLICATION }, - priority: NotificationPriority.URGENT, - sticky: true - } - ); - } + this.notificationService.prompt( + Severity.Warning, + message, + [{ + label: localize('learnMore', "Learn More"), + run: () => this.openerService.open(URI.parse('https://aka.ms/vscode-faq-old-windows')) + }], + { + neverShowAgain: { id: 'windows32eol', isSecondary: true, scope: NeverShowAgainScope.APPLICATION }, + priority: NotificationPriority.URGENT, + sticky: true + } + ); } // Slow shell environment progress indicator From 751a8128bd19c83e67e12c4a1f4c9918d6a3bc5b Mon Sep 17 00:00:00 2001 From: Joe Green Date: Tue, 22 Aug 2023 23:28:36 +0100 Subject: [PATCH 109/221] Fix scroll to top button colour consistency --- src/vs/workbench/contrib/extensions/browser/extensionEditor.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/extensions/browser/extensionEditor.ts b/src/vs/workbench/contrib/extensions/browser/extensionEditor.ts index 366c4d28382..0eb852277ab 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionEditor.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionEditor.ts @@ -803,7 +803,7 @@ export class ExtensionEditor extends EditorPane { #scroll-to-top span.icon::before { content: ""; display: block; - background: var(--vscode-button-foreground); + background: var(--vscode-button-secondaryForeground); /* Chevron up icon */ webkit-mask-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDE5LjIuMCwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPgo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkxheWVyXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IgoJIHZpZXdCb3g9IjAgMCAxNiAxNiIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgMTYgMTY7IiB4bWw6c3BhY2U9InByZXNlcnZlIj4KPHN0eWxlIHR5cGU9InRleHQvY3NzIj4KCS5zdDB7ZmlsbDojRkZGRkZGO30KCS5zdDF7ZmlsbDpub25lO30KPC9zdHlsZT4KPHRpdGxlPnVwY2hldnJvbjwvdGl0bGU+CjxwYXRoIGNsYXNzPSJzdDAiIGQ9Ik04LDUuMWwtNy4zLDcuM0wwLDExLjZsOC04bDgsOGwtMC43LDAuN0w4LDUuMXoiLz4KPHJlY3QgY2xhc3M9InN0MSIgd2lkdGg9IjE2IiBoZWlnaHQ9IjE2Ii8+Cjwvc3ZnPgo='); -webkit-mask-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDE5LjIuMCwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPgo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkxheWVyXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IgoJIHZpZXdCb3g9IjAgMCAxNiAxNiIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgMTYgMTY7IiB4bWw6c3BhY2U9InByZXNlcnZlIj4KPHN0eWxlIHR5cGU9InRleHQvY3NzIj4KCS5zdDB7ZmlsbDojRkZGRkZGO30KCS5zdDF7ZmlsbDpub25lO30KPC9zdHlsZT4KPHRpdGxlPnVwY2hldnJvbjwvdGl0bGU+CjxwYXRoIGNsYXNzPSJzdDAiIGQ9Ik04LDUuMWwtNy4zLDcuM0wwLDExLjZsOC04bDgsOGwtMC43LDAuN0w4LDUuMXoiLz4KPHJlY3QgY2xhc3M9InN0MSIgd2lkdGg9IjE2IiBoZWlnaHQ9IjE2Ii8+Cjwvc3ZnPgo='); From 08b4e30259d6f0372106615e19096740fec3f20c Mon Sep 17 00:00:00 2001 From: Joyce Er Date: Tue, 22 Aug 2023 15:53:56 -0700 Subject: [PATCH 110/221] =?UTF-8?q?=F0=9F=86=99distro=20(#191033)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b878c99812b..425451a5559 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.82.0", - "distro": "505b0336f71abdfa7d1ed0dbaafa20c812fa58e7", + "distro": "1591281180fd2cd18935e6847131d2d4213b7b69", "author": { "name": "Microsoft Corporation" }, From f7ceb0697bbbceb2e2286309ca96cf083e88d7cf Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Wed, 23 Aug 2023 01:27:31 +0200 Subject: [PATCH 111/221] Ports view no longer shows privacy column/toggle (#191037) Fixes #190920 --- .../api/browser/mainThreadTunnelService.ts | 2 +- .../contrib/remote/browser/tunnelView.ts | 57 ++++++++++++++----- 2 files changed, 43 insertions(+), 16 deletions(-) diff --git a/src/vs/workbench/api/browser/mainThreadTunnelService.ts b/src/vs/workbench/api/browser/mainThreadTunnelService.ts index d41e861572b..678285a11c5 100644 --- a/src/vs/workbench/api/browser/mainThreadTunnelService.ts +++ b/src/vs/workbench/api/browser/mainThreadTunnelService.ts @@ -195,10 +195,10 @@ export class MainThreadTunnelService extends Disposable implements MainThreadTun }); } }; - this.tunnelService.setTunnelProvider(tunnelProvider); if (features) { this.tunnelService.setTunnelFeatures(features); } + this.tunnelService.setTunnelProvider(tunnelProvider); // At this point we clearly want the ports view/features since we have a tunnel factory this.contextKeyService.createKey(forwardedPortsViewEnabled.key, true); } diff --git a/src/vs/workbench/contrib/remote/browser/tunnelView.ts b/src/vs/workbench/contrib/remote/browser/tunnelView.ts index ac01011049a..2289a2ece04 100644 --- a/src/vs/workbench/contrib/remote/browser/tunnelView.ts +++ b/src/vs/workbench/contrib/remote/browser/tunnelView.ts @@ -744,7 +744,9 @@ export class TunnelPanel extends ViewPane { static readonly ID = TUNNEL_VIEW_ID; static readonly TITLE = nls.localize('remote.tunnel', "Ports"); + private panelContainer: HTMLElement | undefined; private table!: WorkbenchTable; + private tableDisposables: DisposableStore = this._register(new DisposableStore()); private tunnelTypeContext: IContextKey; private tunnelCloseableContext: IContextKey; private tunnelPrivacyContext: IContextKey; @@ -783,7 +785,7 @@ export class TunnelPanel extends ViewPane { this.tunnelCloseableContext = TunnelCloseableContextKey.bindTo(contextKeyService); this.tunnelPrivacyContext = TunnelPrivacyContextKey.bindTo(contextKeyService); this.tunnelPrivacyEnabledContext = TunnelPrivacyEnabledContextKey.bindTo(contextKeyService); - this.tunnelPrivacyEnabledContext.set(tunnelService.privacyOptions.length !== 0); + this.tunnelPrivacyEnabledContext.set(tunnelService.canChangePrivacy); this.tunnelProtocolContext = TunnelProtocolContextKey.bindTo(contextKeyService); this.tunnelViewFocusContext = TunnelViewFocusContextKey.bindTo(contextKeyService); this.tunnelViewSelectionContext = TunnelViewSelectionContextKey.bindTo(contextKeyService); @@ -806,6 +808,15 @@ export class TunnelPanel extends ViewPane { })); this.registerPrivacyActions(); + this._register(Event.once(this.tunnelService.onAddedTunnelProvider)(() => { + if (this.tunnelPrivacyEnabledContext.get() === false) { + this.tunnelPrivacyEnabledContext.set(tunnelService.canChangePrivacy); + updateActions(); + this.registerPrivacyActions(); + this.createTable(); + this.table.layout(this.height, this.width); + } + })); } private registerPrivacyActions() { @@ -827,11 +838,15 @@ export class TunnelPanel extends ViewPane { return this.remoteExplorerService.tunnelModel.forwarded.size + this.remoteExplorerService.tunnelModel.detected.size; } - protected override renderBody(container: HTMLElement): void { - super.renderBody(container); + private createTable(): void { + if (!this.panelContainer) { + return; + } + this.tableDisposables.clear(); - const panelContainer = dom.append(container, dom.$('.tree-explorer-viewlet-tree-view')); - const widgetContainer = dom.append(panelContainer, dom.$('.customview-tree')); + dom.clearNode(this.panelContainer); + + const widgetContainer = dom.append(this.panelContainer, dom.$('.customview-tree')); widgetContainer.classList.add('ports-view'); widgetContainer.classList.add('file-icon-themable-tree', 'show-file-icons'); @@ -874,18 +889,19 @@ export class TunnelPanel extends ViewPane { const actionRunner: ActionRunner = new ActionRunner(); actionBarRenderer.actionRunner = actionRunner; - this._register(this.table.onContextMenu(e => this.onContextMenu(e, actionRunner))); - this._register(this.table.onMouseDblClick(e => this.onMouseDblClick(e))); - this._register(this.table.onDidChangeFocus(e => this.onFocusChanged(e))); - this._register(this.table.onDidChangeSelection(e => this.onSelectionChanged(e))); - this._register(this.table.onDidFocus(() => this.tunnelViewFocusContext.set(true))); - this._register(this.table.onDidBlur(() => this.tunnelViewFocusContext.set(false))); + this.tableDisposables.add(this.table); + this.tableDisposables.add(this.table.onContextMenu(e => this.onContextMenu(e, actionRunner))); + this.tableDisposables.add(this.table.onMouseDblClick(e => this.onMouseDblClick(e))); + this.tableDisposables.add(this.table.onDidChangeFocus(e => this.onFocusChanged(e))); + this.tableDisposables.add(this.table.onDidChangeSelection(e => this.onSelectionChanged(e))); + this.tableDisposables.add(this.table.onDidFocus(() => this.tunnelViewFocusContext.set(true))); + this.tableDisposables.add(this.table.onDidBlur(() => this.tunnelViewFocusContext.set(false))); const rerender = () => this.table.splice(0, Number.POSITIVE_INFINITY, this.viewModel.all); rerender(); let lastPortCount = this.portCount; - this._register(Event.debounce(this.viewModel.onForwardedPortsChanged, (_last, e) => e, 50)(() => { + this.tableDisposables.add(Event.debounce(this.viewModel.onForwardedPortsChanged, (_last, e) => e, 50)(() => { const newPortCount = this.portCount; if (((lastPortCount === 0) || (newPortCount === 0)) && (lastPortCount !== newPortCount)) { this._onDidChangeViewWelcomeState.fire(); @@ -894,7 +910,7 @@ export class TunnelPanel extends ViewPane { rerender(); })); - this._register(this.table.onMouseClick(e => { + this.tableDisposables.add(this.table.onMouseClick(e => { if (this.hasOpenLinkModifier(e.browserEvent)) { const selection = this.table.getSelectedElements(); if ((selection.length === 0) || @@ -904,7 +920,7 @@ export class TunnelPanel extends ViewPane { } })); - this._register(this.table.onDidOpen(e => { + this.tableDisposables.add(this.table.onDidOpen(e => { if (!e.element || (e.element.tunnelType !== TunnelType.Forwarded)) { return; } @@ -913,7 +929,7 @@ export class TunnelPanel extends ViewPane { } })); - this._register(this.remoteExplorerService.onDidChangeEditable(e => { + this.tableDisposables.add(this.remoteExplorerService.onDidChangeEditable(e => { this.isEditing = !!this.remoteExplorerService.getEditableData(e?.tunnel, e?.editId); this._onDidChangeViewWelcomeState.fire(); @@ -938,6 +954,13 @@ export class TunnelPanel extends ViewPane { })); } + protected override renderBody(container: HTMLElement): void { + super.renderBody(container); + + this.panelContainer = dom.append(container, dom.$('.tree-explorer-viewlet-tree-view')); + this.createTable(); + } + override shouldShowWelcome(): boolean { return this.viewModel.isEmpty() && !this.isEditing; } @@ -1048,7 +1071,11 @@ export class TunnelPanel extends ViewPane { } } + private height = 0; + private width = 0; protected override layoutBody(height: number, width: number): void { + this.height = height; + this.width = width; super.layoutBody(height, width); this.table.layout(height, width); } From 1fe8359ed0ef9c52bd6986565da97c395607a130 Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Tue, 22 Aug 2023 17:29:51 -0700 Subject: [PATCH 112/221] cli: implement 'server of server' for a local web server (#191014) Closes https://github.com/microsoft/vscode/issues/168492 This implements @aeschli's 'server server' concept in a new `code serve-web` command. Command line args are similar to the standalone web server. The first time a user hits that page, the latest version of the VS Code web server will be downloaded and run. Thanks to Martin's previous PRs, all resources the page requests are prefixed with `/`. The latest release version is cached, but when the page is loaded again and there's a new release, a the new server version will be downloaded and started up. Behind the scenes the servers all listen on named pipes/sockets and the CLI acts as a proxy server to those sockets. Servers without connections for an hour will be shut down automatically. --- .vscode/shared.code-snippets | 2 +- cli/Cargo.lock | 4 +- cli/Cargo.toml | 2 +- cli/src/bin/code/main.rs | 6 +- cli/src/commands.rs | 1 + cli/src/commands/args.rs | 31 + cli/src/commands/serve_web.rs | 617 ++++++++++++++++++ cli/src/self_update.rs | 12 +- cli/src/state.rs | 6 + cli/src/tunnels/legal.rs | 19 +- cli/src/update_service.rs | 16 +- cli/src/util/errors.rs | 45 +- cli/src/util/sync.rs | 2 +- src/vs/code/node/cli.ts | 50 +- src/vs/platform/environment/common/argv.ts | 12 +- src/vs/platform/environment/node/argv.ts | 11 + .../platform/environment/node/argvHelper.ts | 6 +- 17 files changed, 753 insertions(+), 89 deletions(-) create mode 100644 cli/src/commands/serve_web.rs diff --git a/.vscode/shared.code-snippets b/.vscode/shared.code-snippets index fb3df23dd42..f473425b76f 100644 --- a/.vscode/shared.code-snippets +++ b/.vscode/shared.code-snippets @@ -6,7 +6,7 @@ // Placeholders with the same ids are connected. // Example: "MSFT Copyright Header": { - "scope": "javascript,typescript,css", + "scope": "javascript,typescript,css,rust", "prefix": [ "header", "stub", diff --git a/cli/Cargo.lock b/cli/Cargo.lock index f7c60045c12..a67cc7cf3bd 100644 --- a/cli/Cargo.lock +++ b/cli/Cargo.lock @@ -983,9 +983,9 @@ dependencies = [ [[package]] name = "http" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" +checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" dependencies = [ "bytes", "fnv", diff --git a/cli/Cargo.toml b/cli/Cargo.toml index a25bee1f2ce..18f18069c1f 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -37,7 +37,7 @@ libc = "0.2.144" tunnels = { git = "https://github.com/microsoft/dev-tunnels", rev = "2621784a9ad72aa39500372391332a14bad581a3", default-features = false, features = ["connections"] } keyring = { version = "2.0.3", default-features = false, features = ["linux-secret-service-rt-tokio-crypto-openssl"] } dialoguer = "0.10.4" -hyper = "0.14.26" +hyper = { version = "0.14.26", features = ["server", "http1", "runtime"] } indicatif = "0.17.4" tempfile = "3.5.0" clap_lex = "0.5.0" diff --git a/cli/src/bin/code/main.rs b/cli/src/bin/code/main.rs index 8c32ee14d89..b104976b9ab 100644 --- a/cli/src/bin/code/main.rs +++ b/cli/src/bin/code/main.rs @@ -8,7 +8,7 @@ use std::process::Command; use clap::Parser; use cli::{ - commands::{args, tunnels, update, version, CommandContext}, + commands::{args, serve_web, tunnels, update, version, CommandContext}, constants::get_default_user_agent, desktop, log, state::LauncherPaths, @@ -99,6 +99,10 @@ async fn main() -> Result<(), std::convert::Infallible> { tunnels::command_shell(context!(), cs_args).await } + Some(args::Commands::ServeWeb(sw_args)) => { + serve_web::serve_web(context!(), sw_args).await + } + Some(args::Commands::Tunnel(tunnel_args)) => match tunnel_args.subcommand { Some(args::TunnelSubcommand::Prune) => tunnels::prune(context!()).await, Some(args::TunnelSubcommand::Unregister) => tunnels::unregister(context!()).await, diff --git a/cli/src/commands.rs b/cli/src/commands.rs index 754729f2c04..d10a52ad774 100644 --- a/cli/src/commands.rs +++ b/cli/src/commands.rs @@ -9,4 +9,5 @@ pub mod args; pub mod tunnels; pub mod update; pub mod version; +pub mod serve_web; pub use context::CommandContext; diff --git a/cli/src/commands/args.rs b/cli/src/commands/args.rs index 9caee09ed64..cce01c52fd9 100644 --- a/cli/src/commands/args.rs +++ b/cli/src/commands/args.rs @@ -172,11 +172,42 @@ pub enum Commands { /// Changes the version of the editor you're using. Version(VersionArgs), + /// Runs a local web version of VS Code. + ServeWeb(ServeWebArgs), + /// Runs the control server on process stdin/stdout #[clap(hide = true)] CommandShell(CommandShellArgs), } +#[derive(Args, Debug, Clone)] +pub struct ServeWebArgs { + /// Host to listen on, defaults to 'localhost' + #[clap(long)] + pub host: Option, + /// Port to listen on. If 0 is passed a random free port is picked. + #[clap(long, default_value_t = 8000)] + pub port: u16, + /// A secret that must be included with all requests. + #[clap(long)] + pub connection_token: Option, + /// Run without a connection token. Only use this if the connection is secured by other means. + #[clap(long)] + pub without_connection_token: bool, + /// If set, the user accepts the server license terms and the server will be started without a user prompt. + #[clap(long)] + pub accept_server_license_terms: bool, + /// Specifies the directory that server data is kept in. + #[clap(long)] + pub server_data_dir: Option, + /// Specifies the directory that user data is kept in. Can be used to open multiple distinct instances of Code. + #[clap(long)] + pub user_data_dir: Option, + /// Set the root path for extensions. + #[clap(long)] + pub extensions_dir: Option, +} + #[derive(Args, Debug, Clone)] pub struct CommandShellArgs { /// Listen on a socket instead of stdin/stdout. diff --git a/cli/src/commands/serve_web.rs b/cli/src/commands/serve_web.rs new file mode 100644 index 00000000000..b2bf4d431e4 --- /dev/null +++ b/cli/src/commands/serve_web.rs @@ -0,0 +1,617 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +use std::collections::HashMap; +use std::convert::Infallible; +use std::net::{IpAddr, Ipv4Addr, SocketAddr}; +use std::path::PathBuf; +use std::sync::{Arc, Mutex}; +use std::time::{Duration, Instant}; + +use hyper::service::{make_service_fn, service_fn}; +use hyper::{Body, Request, Response, Server}; +use tokio::io::{AsyncBufReadExt, BufReader}; +use tokio::pin; +use tokio::process::Command; + +use crate::async_pipe::{get_socket_name, get_socket_rw_stream, AsyncPipe}; +use crate::constants::VSCODE_CLI_QUALITY; +use crate::download_cache::DownloadCache; +use crate::log; +use crate::options::Quality; +use crate::update_service::{ + unzip_downloaded_release, Platform, Release, TargetKind, UpdateService, +}; +use crate::util::errors::AnyError; +use crate::util::http::{self, ReqwestSimpleHttp}; +use crate::util::io::SilentCopyProgress; +use crate::util::sync::{new_barrier, Barrier, BarrierOpener}; +use crate::{ + tunnels::legal, + util::{errors::CodeError, prereqs::PreReqChecker}, +}; + +use super::{args::ServeWebArgs, CommandContext}; + +/// Length of a commit hash, for validation +const COMMIT_HASH_LEN: usize = 40; +/// Number of seconds where, if there's no connections to a VS Code server, +/// the server is shut down. +const SERVER_IDLE_TIMEOUT_SECS: u64 = 60 * 60; +/// Number of seconds in which the server times out when there is a connection +/// (should be large enough to basically never happen) +const SERVER_ACTIVE_TIMEOUT_SECS: u64 = SERVER_IDLE_TIMEOUT_SECS * 24 * 30 * 12; +/// How long to cache the "latest" version we get from the update service. +const RELEASE_CACHE_SECS: u64 = 60 * 60; + +/// Implements the vscode "server of servers". Clients who go to the URI get +/// served the latest version of the VS Code server whenever they load the +/// page. The VS Code server prefixes all assets and connections it loads with +/// its version string, so existing clients can continue to get served even +/// while new clients get new VS Code Server versions. +pub async fn serve_web(ctx: CommandContext, mut args: ServeWebArgs) -> Result { + legal::require_consent(&ctx.paths, args.accept_server_license_terms)?; + let mut addr: SocketAddr = match &args.host { + Some(h) => h.parse().map_err(CodeError::InvalidHostAddress)?, + None => SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 0), + }; + addr.set_port(args.port); + + let platform: crate::update_service::Platform = PreReqChecker::new().verify().await?; + + if !args.without_connection_token { + // Ensure there's a defined connection token, since if multiple server versions + // are excuted, they will need to have a single shared token. + let connection_token = args + .connection_token + .clone() + .unwrap_or_else(|| uuid::Uuid::new_v4().to_string()); + ctx.log.result(format!( + "Web UI available at http://{}?tkn={}", + addr, connection_token, + )); + args.connection_token = Some(connection_token); + } else { + ctx.log + .result(format!("Web UI available at http://{}", addr)); + args.connection_token = None; + } + + let cm = ConnectionManager::new(&ctx, platform, args); + let make_svc = make_service_fn(move |_conn| { + let cm = cm.clone(); + let log = ctx.log.clone(); + let service = service_fn(move |req| handle(cm.clone(), log.clone(), req)); + async move { Ok::<_, Infallible>(service) } + }); + + let server = Server::bind(&addr).serve(make_svc); + + server.await.map_err(CodeError::CouldNotListenOnInterface)?; + + Ok(0) +} + +/// Handler function for an inbound request +async fn handle( + cm: Arc, + log: log::Logger, + req: Request, +) -> Result, Infallible> { + let release = if let Some((r, _)) = get_release_from_path(req.uri().path(), cm.platform) { + r + } else { + match cm.get_latest_release().await { + Ok(r) => r, + Err(e) => { + error!(log, "error getting latest version: {}", e); + return Ok(response::code_err(e)); + } + } + }; + + Ok(match cm.get_connection(release).await { + Ok(rw) => { + if req.headers().contains_key(hyper::header::UPGRADE) { + forward_ws_req_to_server(cm.log.clone(), rw, req).await + } else { + forward_http_req_to_server(rw, req).await + } + } + Err(CodeError::ServerNotYetDownloaded) => response::wait_for_download(), + Err(e) => response::code_err(e), + }) +} + +/// Gets the release info from the VS Code path prefix, which is in the +/// format `/-/...` +fn get_release_from_path(path: &str, platform: Platform) -> Option<(Release, String)> { + if !path.starts_with('/') { + return None; // paths must start with '/' + } + + let path = &path[1..]; + let i = path.find('/').unwrap_or(path.len()); + let quality_commit_sep = path.get(..i).and_then(|p| p.find('-'))?; + + let (quality_commit, remaining) = path.split_at(i); + let (quality, commit) = quality_commit.split_at(quality_commit_sep); + + if !is_commit_hash(commit) { + return None; + } + + Some(( + Release { + // remember to trim off the leading '/' which is now part of th quality + quality: Quality::try_from(quality).ok()?, + commit: commit.to_string(), + platform, + target: TargetKind::Web, + name: "".to_string(), + }, + remaining.to_string(), + )) +} + +/// Proxies the standard HTTP request to the async pipe, returning the piped response +async fn forward_http_req_to_server( + (rw, handle): (AsyncPipe, ConnectionHandle), + req: Request, +) -> Response { + let (mut request_sender, connection) = + match hyper::client::conn::Builder::new().handshake(rw).await { + Ok(r) => r, + Err(e) => return response::connection_err(e), + }; + + tokio::spawn(connection); + + let res = request_sender + .send_request(req) + .await + .unwrap_or_else(response::connection_err); + + // technically, we should buffer the body into memory since it may not be + // read at this point, but because the keepalive time is very large + // there's not going to be responses that take hours to send and x + // cause us to kill the server before the response is sent + drop(handle); + + res +} + +/// Proxies the websocket request to the async pipe +async fn forward_ws_req_to_server( + log: log::Logger, + (rw, handle): (AsyncPipe, ConnectionHandle), + mut req: Request, +) -> Response { + // splicing of client and servers inspired by https://github.com/hyperium/hyper/blob/fece9f7f50431cf9533cfe7106b53a77b48db699/examples/upgrades.rs + let (mut request_sender, connection) = + match hyper::client::conn::Builder::new().handshake(rw).await { + Ok(r) => r, + Err(e) => return response::connection_err(e), + }; + + tokio::spawn(connection); + + let mut proxied_req = Request::builder().uri(req.uri()); + for (k, v) in req.headers() { + proxied_req = proxied_req.header(k, v); + } + + let mut res = request_sender + .send_request(proxied_req.body(Body::empty()).unwrap()) + .await + .unwrap_or_else(response::connection_err); + + let mut proxied_res = Response::new(Body::empty()); + *proxied_res.status_mut() = res.status(); + for (k, v) in res.headers() { + proxied_res.headers_mut().insert(k, v.clone()); + } + + // only start upgrade at this point in case the server decides to deny socket + if res.status() == hyper::StatusCode::SWITCHING_PROTOCOLS { + tokio::spawn(async move { + let (s_req, s_res) = + tokio::join!(hyper::upgrade::on(&mut req), hyper::upgrade::on(&mut res)); + + match (s_req, s_res) { + (Err(e1), Err(e2)) => debug!( + log, + "client ({}) and server ({}) websocket upgrade failed", e1, e2 + ), + (Err(e1), _) => debug!(log, "client ({}) websocket upgrade failed", e1), + (_, Err(e2)) => debug!(log, "server ({}) websocket upgrade failed", e2), + (Ok(mut s_req), Ok(mut s_res)) => { + trace!(log, "websocket upgrade succeeded"); + let r = tokio::io::copy_bidirectional(&mut s_req, &mut s_res).await; + trace!(log, "websocket closed (error: {:?})", r.err()); + } + } + + drop(handle); + }); + } + + proxied_res +} + +/// Returns whether the string looks like a commit hash. +fn is_commit_hash(s: &str) -> bool { + s.len() == COMMIT_HASH_LEN && s.chars().all(|c| c.is_ascii_hexdigit()) +} + +/// Module holding original responses the CLI's server makes. +mod response { + use const_format::concatcp; + + use crate::constants::QUALITYLESS_SERVER_NAME; + + use super::*; + + pub fn connection_err(err: hyper::Error) -> Response { + Response::builder() + .status(503) + .body(Body::from(format!("Error connecting to server: {:?}", err))) + .unwrap() + } + + pub fn code_err(err: CodeError) -> Response { + Response::builder() + .status(500) + .body(Body::from(format!("Error serving request: {}", err))) + .unwrap() + } + + pub fn wait_for_download() -> Response { + Response::builder() + .status(202) + .header("Content-Type", "text/html") // todo: get latest + .body(Body::from(concatcp!("The latest version of the ", QUALITYLESS_SERVER_NAME, " is downloading, please wait a moment...", ))) + .unwrap() + } +} + +/// Handle returned when getting a stream to the server, used to refcount +/// connections to a server so it can be disposed when there are no more clients. +struct ConnectionHandle { + client_counter: Arc>, +} + +impl ConnectionHandle { + pub fn new(client_counter: Arc>) -> Self { + client_counter.send_modify(|v| { + *v += 1; + }); + Self { client_counter } + } +} + +impl Drop for ConnectionHandle { + fn drop(&mut self) { + self.client_counter.send_modify(|v| { + *v -= 1; + }); + } +} + +type StartData = (PathBuf, Arc>); + +/// State stored in the ConnectionManager for each server version. +struct VersionState { + downloaded: bool, + socket_path: Barrier>, +} + +type ConnectionStateMap = Arc>>; + +/// Manages the connections to running web UI instances. Multiple web servers +/// can run concurrently, with routing based on the URL path. +struct ConnectionManager { + pub platform: Platform, + pub log: log::Logger, + args: ServeWebArgs, + /// Cache where servers are stored + cache: DownloadCache, + /// Mapping of (Quality, Commit) to the state each server is in + state: ConnectionStateMap, + /// Update service instance + update_service: UpdateService, + /// Cache of the latest released version, storing the time we checked as well + latest_version: tokio::sync::Mutex>, +} + +fn key_for_release(release: &Release) -> (Quality, String) { + (release.quality, release.commit.clone()) +} + +impl ConnectionManager { + pub fn new(ctx: &CommandContext, platform: Platform, args: ServeWebArgs) -> Arc { + Arc::new(Self { + platform, + args, + log: ctx.log.clone(), + cache: DownloadCache::new(ctx.paths.web_server_storage()), + update_service: UpdateService::new( + ctx.log.clone(), + Arc::new(ReqwestSimpleHttp::with_client(ctx.http.clone())), + ), + state: ConnectionStateMap::default(), + latest_version: tokio::sync::Mutex::default(), + }) + } + + /// Gets a connection to a server version + pub async fn get_connection( + &self, + release: Release, + ) -> Result<(AsyncPipe, ConnectionHandle), CodeError> { + // todo@connor4312: there is likely some performance benefit to + // implementing a 'keepalive' for these connections. + let (path, counter) = self.get_version_data(release).await?; + let handle = ConnectionHandle::new(counter); + let rw = get_socket_rw_stream(&path).await?; + Ok((rw, handle)) + } + + /// Gets the latest release for the CLI quality, caching its result for some + /// time to allow for fast loads. + pub async fn get_latest_release(&self) -> Result { + let mut latest = self.latest_version.lock().await; + let now = Instant::now(); + if let Some((checked_at, release)) = &*latest { + if checked_at.elapsed() < Duration::from_secs(RELEASE_CACHE_SECS) { + return Ok(release.clone()); + } + } + + let quality = VSCODE_CLI_QUALITY + .ok_or_else(|| CodeError::UpdatesNotConfigured("no configured quality")) + .and_then(|q| { + Quality::try_from(q).map_err(|_| CodeError::UpdatesNotConfigured("unknown quality")) + })?; + + let release = self + .update_service + .get_latest_commit(self.platform, TargetKind::Web, quality) + .await + .map_err(|e| CodeError::UpdateCheckFailed(e.to_string())); + + // If the update service is unavailable and we have stale data, use that + if let (Err(e), Some((_, previous))) = (&release, &*latest) { + warning!(self.log, "error getting latest release, using stale: {}", e); + return Ok(previous.clone()); + } + + let release = release?; + debug!(self.log, "refreshed latest release: {}", release); + *latest = Some((now, release.clone())); + + Ok(release) + } + + /// Gets the StartData for the a version of the VS Code server, triggering + /// download/start if necessary. It returns `CodeError::ServerNotYetDownloaded` + /// while the server is downloading, which is used to have a refresh loop on the page. + async fn get_version_data(&self, release: Release) -> Result { + self.get_version_data_inner(release)? + .wait() + .await + .unwrap() + .map_err(CodeError::ServerDownloadError) + } + + fn get_version_data_inner( + &self, + release: Release, + ) -> Result>, CodeError> { + let mut state = self.state.lock().unwrap(); + let key = key_for_release(&release); + if let Some(s) = state.get_mut(&key) { + if !s.downloaded { + if s.socket_path.is_open() { + s.downloaded = true; + } else { + return Err(CodeError::ServerNotYetDownloaded); + } + } + + return Ok(s.socket_path.clone()); + } + + let (socket_path, opener) = new_barrier(); + let state_map_dup = self.state.clone(); + let args = StartArgs { + args: self.args.clone(), + log: self.log.clone(), + opener, + release, + }; + + if let Some(p) = self.cache.exists(&args.release.commit) { + state.insert( + key.clone(), + VersionState { + socket_path: socket_path.clone(), + downloaded: true, + }, + ); + + tokio::spawn(async move { + Self::start_version(args, p).await; + state_map_dup.lock().unwrap().remove(&key); + }); + Ok(socket_path) + } else { + state.insert( + key.clone(), + VersionState { + socket_path, + downloaded: false, + }, + ); + let update_service = self.update_service.clone(); + let cache = self.cache.clone(); + tokio::spawn(async move { + Self::download_version(args, update_service.clone(), cache.clone()).await; + state_map_dup.lock().unwrap().remove(&key); + }); + Err(CodeError::ServerNotYetDownloaded) + } + } + + /// Downloads a server version into the cache and starts it. + async fn download_version( + args: StartArgs, + update_service: UpdateService, + cache: DownloadCache, + ) { + let release_for_fut = args.release.clone(); + let log_for_fut = args.log.clone(); + let dir_fut = cache.create(&args.release.commit, |target_dir| async move { + info!(log_for_fut, "Downloading server {}", release_for_fut.commit); + let tmpdir = tempfile::tempdir().unwrap(); + let response = update_service.get_download_stream(&release_for_fut).await?; + + let name = response.url_path_basename().unwrap(); + let archive_path = tmpdir.path().join(name); + http::download_into_file( + &archive_path, + log_for_fut.get_download_logger("Downloading server:"), + response, + ) + .await?; + unzip_downloaded_release(&archive_path, &target_dir, SilentCopyProgress())?; + Ok(()) + }); + + match dir_fut.await { + Err(e) => args.opener.open(Err(e.to_string())), + Ok(dir) => Self::start_version(args, dir).await, + } + } + + /// Starts a downloaded server that can be found in the given `path`. + async fn start_version(args: StartArgs, path: PathBuf) { + info!(args.log, "Starting server {}", args.release.commit); + + let executable = path + .join("bin") + .join(args.release.quality.server_entrypoint()); + let socket_path = get_socket_name(); + + #[cfg(not(windows))] + let mut cmd = Command::new(&executable); + #[cfg(windows)] + let mut cmd = { + let mut cmd = Command::new("cmd"); + cmd.arg("/Q"); + cmd.arg("/C"); + cmd.arg(&executable); + cmd + }; + + cmd.stdin(std::process::Stdio::null()); + cmd.stderr(std::process::Stdio::piped()); + cmd.stdout(std::process::Stdio::piped()); + cmd.arg("--socket-path"); + cmd.arg(&socket_path); + + // License agreement already checked by the `server_web` function. + cmd.args(["--accept-server-license-terms"]); + + if let Some(a) = &args.args.server_data_dir { + cmd.arg("--server-data-dir"); + cmd.arg(a); + } + if let Some(a) = &args.args.user_data_dir { + cmd.arg("--user-data-dir"); + cmd.arg(a); + } + if let Some(a) = &args.args.extensions_dir { + cmd.arg("--extensions-dir"); + cmd.arg(a); + } + if args.args.without_connection_token { + cmd.arg("--without-connection-token"); + } + if let Some(ct) = &args.args.connection_token { + cmd.arg("--connection-token"); + cmd.arg(ct); + } + + // removed, otherwise the workbench will not be usable when running the CLI from sources. + cmd.env_remove("VSCODE_DEV"); + + let mut child = match cmd.spawn() { + Ok(c) => c, + Err(e) => { + args.opener.open(Err(e.to_string())); + return; + } + }; + + let (mut stdout, mut stderr) = ( + BufReader::new(child.stdout.take().unwrap()).lines(), + BufReader::new(child.stderr.take().unwrap()).lines(), + ); + + // wrapped option to prove that we only use this once in the loop + let (counter_tx, mut counter_rx) = tokio::sync::watch::channel(0); + let mut opener = Some((args.opener, socket_path, Arc::new(counter_tx))); + let commit_prefix = &args.release.commit[..7]; + let kill_timer = tokio::time::sleep(Duration::from_secs(SERVER_IDLE_TIMEOUT_SECS)); + pin!(kill_timer); + + loop { + tokio::select! { + Ok(Some(l)) = stdout.next_line() => { + info!(args.log, "[{} stdout]: {}", commit_prefix, l); + + if l.contains("Server bound to") { + if let Some((opener, path, counter_tx)) = opener.take() { + opener.open(Ok((path, counter_tx))); + } + } + } + Ok(Some(l)) = stderr.next_line() => { + info!(args.log, "[{} stderr]: {}", commit_prefix, l); + }, + n = counter_rx.changed() => { + kill_timer.as_mut().reset(match n { + // err means that the record was dropped + Err(_) => tokio::time::Instant::now(), + Ok(_) => { + if *counter_rx.borrow() == 0 { + tokio::time::Instant::now() + Duration::from_secs(SERVER_IDLE_TIMEOUT_SECS) + } else { + tokio::time::Instant::now() + Duration::from_secs(SERVER_ACTIVE_TIMEOUT_SECS) + } + } + }); + } + _ = &mut kill_timer => { + info!(args.log, "[{} process]: idle timeout reached, ending", commit_prefix); + let _ = child.kill().await; + break; + } + e = child.wait() => { + info!(args.log, "[{} process]: exited: {:?}", commit_prefix, e); + break; + } + } + } + } +} + +struct StartArgs { + log: log::Logger, + args: ServeWebArgs, + release: Release, + opener: BarrierOpener>, +} diff --git a/cli/src/self_update.rs b/cli/src/self_update.rs index 2e95719a3b9..4a878dc5447 100644 --- a/cli/src/self_update.rs +++ b/cli/src/self_update.rs @@ -11,7 +11,7 @@ use crate::{ options::Quality, update_service::{unzip_downloaded_release, Platform, Release, TargetKind, UpdateService}, util::{ - errors::{wrap, AnyError, CorruptDownload, UpdatesNotConfigured}, + errors::{wrap, AnyError, CodeError, CorruptDownload}, http, io::{ReportCopyProgress, SilentCopyProgress}, }, @@ -27,14 +27,16 @@ pub struct SelfUpdate<'a> { impl<'a> SelfUpdate<'a> { pub fn new(update_service: &'a UpdateService) -> Result { let commit = VSCODE_CLI_COMMIT - .ok_or_else(|| UpdatesNotConfigured("unknown build commit".to_string()))?; + .ok_or_else(|| CodeError::UpdatesNotConfigured("unknown build commit"))?; let quality = VSCODE_CLI_QUALITY - .ok_or_else(|| UpdatesNotConfigured("no configured quality".to_string())) - .and_then(|q| Quality::try_from(q).map_err(UpdatesNotConfigured))?; + .ok_or_else(|| CodeError::UpdatesNotConfigured("no configured quality")) + .and_then(|q| { + Quality::try_from(q).map_err(|_| CodeError::UpdatesNotConfigured("unknown quality")) + })?; let platform = Platform::env_default().ok_or_else(|| { - UpdatesNotConfigured("Unknown platform, please report this error".to_string()) + CodeError::UpdatesNotConfigured("Unknown platform, please report this error") })?; Ok(Self { diff --git a/cli/src/state.rs b/cli/src/state.rs index 1b1ff343da5..8815e2df40c 100644 --- a/cli/src/state.rs +++ b/cli/src/state.rs @@ -212,4 +212,10 @@ impl LauncherPaths { ) }) } + + /// Suggested path for web server storage + pub fn web_server_storage(&self) -> PathBuf { + self.root.join("serve-web") + } + } diff --git a/cli/src/tunnels/legal.rs b/cli/src/tunnels/legal.rs index 676ccb7da55..35316af4fde 100644 --- a/cli/src/tunnels/legal.rs +++ b/cli/src/tunnels/legal.rs @@ -2,9 +2,9 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -use crate::constants::{IS_INTERACTIVE_CLI, PRODUCT_NAME_LONG}; +use crate::constants::IS_INTERACTIVE_CLI; use crate::state::{LauncherPaths, PersistedState}; -use crate::util::errors::{AnyError, MissingLegalConsent}; +use crate::util::errors::{AnyError, CodeError}; use crate::util::input::prompt_yn; use lazy_static::lazy_static; use serde::{Deserialize, Serialize}; @@ -46,23 +46,14 @@ pub fn require_consent( if accept_server_license_terms { load.consented = Some(true); } else if !*IS_INTERACTIVE_CLI { - return Err(MissingLegalConsent( - "Run this command again with --accept-server-license-terms to indicate your agreement." - .to_string(), - ) - .into()); + return Err(CodeError::NeedsInteractiveLegalConsent.into()); } else { match prompt_yn(prompt) { Ok(true) => { load.consented = Some(true); } - Ok(false) => { - return Err(AnyError::from(MissingLegalConsent(format!( - "Sorry you cannot use {} CLI without accepting the terms.", - PRODUCT_NAME_LONG - )))) - } - Err(e) => return Err(AnyError::from(MissingLegalConsent(e.to_string()))), + Ok(false) => return Err(CodeError::DeniedLegalConset.into()), + Err(_) => return Err(CodeError::NeedsInteractiveLegalConsent.into()), } } diff --git a/cli/src/update_service.rs b/cli/src/update_service.rs index b03d8ea5963..d218e4a1333 100644 --- a/cli/src/update_service.rs +++ b/cli/src/update_service.rs @@ -11,7 +11,7 @@ use crate::{ constants::VSCODE_CLI_UPDATE_ENDPOINT, debug, log, options, spanf, util::{ - errors::{AnyError, CodeError, UpdatesNotConfigured, WrappedError}, + errors::{AnyError, CodeError, WrappedError}, http::{BoxedHttp, SimpleResponse}, io::ReportCopyProgress, tar, zipper, @@ -19,6 +19,7 @@ use crate::{ }; /// Implementation of the VS Code Update service for use in the CLI. +#[derive(Clone)] pub struct UpdateService { client: BoxedHttp, log: log::Logger, @@ -54,6 +55,10 @@ fn quality_download_segment(quality: options::Quality) -> &'static str { } } +fn get_update_endpoint() -> Result<&'static str, CodeError> { + VSCODE_CLI_UPDATE_ENDPOINT.ok_or_else(|| CodeError::UpdatesNotConfigured("no service url")) +} + impl UpdateService { pub fn new(log: log::Logger, http: BoxedHttp) -> Self { UpdateService { client: http, log } @@ -66,8 +71,7 @@ impl UpdateService { quality: options::Quality, version: &str, ) -> Result { - let update_endpoint = - VSCODE_CLI_UPDATE_ENDPOINT.ok_or_else(UpdatesNotConfigured::no_url)?; + let update_endpoint = get_update_endpoint()?; let download_segment = target .download_segment(platform) .ok_or_else(|| CodeError::UnsupportedPlatform(platform.to_string()))?; @@ -108,8 +112,7 @@ impl UpdateService { target: TargetKind, quality: options::Quality, ) -> Result { - let update_endpoint = - VSCODE_CLI_UPDATE_ENDPOINT.ok_or_else(UpdatesNotConfigured::no_url)?; + let update_endpoint = get_update_endpoint()?; let download_segment = target .download_segment(platform) .ok_or_else(|| CodeError::UnsupportedPlatform(platform.to_string()))?; @@ -144,8 +147,7 @@ impl UpdateService { /// Gets the download stream for the release. pub async fn get_download_stream(&self, release: &Release) -> Result { - let update_endpoint = - VSCODE_CLI_UPDATE_ENDPOINT.ok_or_else(UpdatesNotConfigured::no_url)?; + let update_endpoint = get_update_endpoint()?; let download_segment = release .target .download_segment(release.platform) diff --git a/cli/src/util/errors.rs b/cli/src/util/errors.rs index c82e14acc8b..38d9b36f54b 100644 --- a/cli/src/util/errors.rs +++ b/cli/src/util/errors.rs @@ -108,16 +108,6 @@ impl StatusError { } } -// When the user has not consented to the licensing terms in using the Launcher -#[derive(Debug)] -pub struct MissingLegalConsent(pub String); - -impl std::fmt::Display for MissingLegalConsent { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(f, "{}", self.0) - } -} - // When the provided connection token doesn't match the one used to set up the original VS Code Server // This is most likely due to a new user joining. #[derive(Debug)] @@ -313,20 +303,6 @@ impl std::fmt::Display for ServerHasClosed { } } -#[derive(Debug)] -pub struct UpdatesNotConfigured(pub String); - -impl UpdatesNotConfigured { - pub fn no_url() -> Self { - UpdatesNotConfigured("no service url".to_owned()) - } -} - -impl std::fmt::Display for UpdatesNotConfigured { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(f, "Update service is not configured: {}", self.0) - } -} #[derive(Debug)] pub struct ServiceAlreadyRegistered(); @@ -517,10 +493,28 @@ pub enum CodeError { KeyringTimeout, #[error("no host is connected to the tunnel relay")] NoTunnelEndpoint, + #[error("could not parse `host`: {0}")] + InvalidHostAddress(std::net::AddrParseError), + #[error("could not start server on the given host/port: {0}")] + CouldNotListenOnInterface(hyper::Error), + #[error( + "Run this command again with --accept-server-license-terms to indicate your agreement." + )] + NeedsInteractiveLegalConsent, + #[error("Sorry, you cannot use this CLI without accepting the terms.")] + DeniedLegalConset, + #[error("The server is not yet downloaded, try again shortly.")] + ServerNotYetDownloaded, + #[error("An error was encountered downloading the server, please retry: {0}")] + ServerDownloadError(String), + #[error("Updates are are not available: {0}")] + UpdatesNotConfigured(&'static str), + // todo: can be specialized when update service is moved to CodeErrors + #[error("Could not check for update: {0}")] + UpdateCheckFailed(String), } makeAnyError!( - MissingLegalConsent, MismatchConnectionToken, DevTunnelError, StatusError, @@ -543,7 +537,6 @@ makeAnyError!( ServerHasClosed, ServiceAlreadyRegistered, WindowsNeedsElevation, - UpdatesNotConfigured, CorruptDownload, MissingHomeDirectory, OAuthError, diff --git a/cli/src/util/sync.rs b/cli/src/util/sync.rs index 8b653cd2d53..67c777b75ed 100644 --- a/cli/src/util/sync.rs +++ b/cli/src/util/sync.rs @@ -63,7 +63,7 @@ impl BarrierOpener { /// and is thereafter permanently closed. It can contain a value. pub fn new_barrier() -> (Barrier, BarrierOpener) where - T: Copy, + T: Clone, { let (closed_tx, closed_rx) = watch::channel(None); (Barrier(closed_rx), BarrierOpener(Arc::new(closed_tx))) diff --git a/src/vs/code/node/cli.ts b/src/vs/code/node/cli.ts index 3b823317303..4770e9ef0bd 100644 --- a/src/vs/code/node/cli.ts +++ b/src/vs/code/node/cli.ts @@ -15,7 +15,7 @@ import { whenDeleted, writeFileSync } from 'vs/base/node/pfs'; import { findFreePort } from 'vs/base/node/ports'; import { watchFileContents } from 'vs/platform/files/node/watcher/nodejs/nodejsWatcherLib'; import { NativeParsedArgs } from 'vs/platform/environment/common/argv'; -import { buildHelpMessage, buildVersionMessage, OPTIONS } from 'vs/platform/environment/node/argv'; +import { buildHelpMessage, buildVersionMessage, NATIVE_CLI_COMMANDS, OPTIONS } from 'vs/platform/environment/node/argv'; import { addArg, parseCLIProcessArgv } from 'vs/platform/environment/node/argvHelper'; import { getStdinFilePath, hasStdinWithoutTty, readFromStdin, stdinDataListener } from 'vs/platform/environment/node/stdin'; import { createWaitMarkerFileSync } from 'vs/platform/environment/node/wait'; @@ -51,31 +51,33 @@ export async function main(argv: string[]): Promise { return; } - if (args.tunnel) { - if (!product.tunnelApplicationName) { - console.error(`'tunnel' command not supported in ${product.applicationName}`); - return; - } - const tunnelArgs = argv.slice(argv.indexOf('tunnel') + 1); // all arguments behind `tunnel` - return new Promise((resolve, reject) => { - let tunnelProcess: ChildProcess; - const stdio: StdioOptions = ['ignore', 'pipe', 'pipe']; - if (process.env['VSCODE_DEV']) { - tunnelProcess = spawn('cargo', ['run', '--', 'tunnel', ...tunnelArgs], { cwd: join(getAppRoot(), 'cli'), stdio }); - } else { - const appPath = process.platform === 'darwin' - // ./Contents/MacOS/Electron => ./Contents/Resources/app/bin/code-tunnel-insiders - ? join(dirname(dirname(process.execPath)), 'Resources', 'app') - : dirname(process.execPath); - const tunnelCommand = join(appPath, 'bin', `${product.tunnelApplicationName}${isWindows ? '.exe' : ''}`); - tunnelProcess = spawn(tunnelCommand, ['tunnel', ...tunnelArgs], { cwd: cwd(), stdio }); + for (const subcommand of NATIVE_CLI_COMMANDS) { + if (args[subcommand]) { + if (!product.tunnelApplicationName) { + console.error(`'${subcommand}' command not supported in ${product.applicationName}`); + return; } + const tunnelArgs = argv.slice(argv.indexOf(subcommand) + 1); // all arguments behind `tunnel` + return new Promise((resolve, reject) => { + let tunnelProcess: ChildProcess; + const stdio: StdioOptions = ['ignore', 'pipe', 'pipe']; + if (process.env['VSCODE_DEV']) { + tunnelProcess = spawn('cargo', ['run', '--', subcommand, ...tunnelArgs], { cwd: join(getAppRoot(), 'cli'), stdio }); + } else { + const appPath = process.platform === 'darwin' + // ./Contents/MacOS/Electron => ./Contents/Resources/app/bin/code-tunnel-insiders + ? join(dirname(dirname(process.execPath)), 'Resources', 'app') + : dirname(process.execPath); + const tunnelCommand = join(appPath, 'bin', `${product.tunnelApplicationName}${isWindows ? '.exe' : ''}`); + tunnelProcess = spawn(tunnelCommand, [subcommand, ...tunnelArgs], { cwd: cwd(), stdio }); + } - tunnelProcess.stdout!.pipe(process.stdout); - tunnelProcess.stderr!.pipe(process.stderr); - tunnelProcess.on('exit', resolve); - tunnelProcess.on('error', reject); - }); + tunnelProcess.stdout!.pipe(process.stdout); + tunnelProcess.stderr!.pipe(process.stderr); + tunnelProcess.on('exit', resolve); + tunnelProcess.on('error', reject); + }); + } } // Help diff --git a/src/vs/platform/environment/common/argv.ts b/src/vs/platform/environment/common/argv.ts index 17476d94187..b63a262137f 100644 --- a/src/vs/platform/environment/common/argv.ts +++ b/src/vs/platform/environment/common/argv.ts @@ -3,15 +3,18 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +export interface INativeCliOptions { + 'cli-data-dir'?: string; + 'disable-telemetry'?: boolean; + 'telemetry-level'?: string; +} + /** * A list of command line arguments we support natively. */ export interface NativeParsedArgs { // subcommands - tunnel?: { - 'cli-data-dir'?: string; - 'disable-telemetry'?: boolean; - 'telemetry-level'?: string; + tunnel?: INativeCliOptions & { user: { login: { 'access-token'?: string; @@ -19,6 +22,7 @@ export interface NativeParsedArgs { }; }; }; + 'serve-web'?: INativeCliOptions; _: string[]; 'folder-uri'?: string[]; // undefined or array of 1 or more 'file-uri'?: string[]; // undefined or array of 1 or more diff --git a/src/vs/platform/environment/node/argv.ts b/src/vs/platform/environment/node/argv.ts index b3e423e20f9..63243fcf3a0 100644 --- a/src/vs/platform/environment/node/argv.ts +++ b/src/vs/platform/environment/node/argv.ts @@ -44,6 +44,8 @@ export type OptionDescriptions = { Subcommand }; +export const NATIVE_CLI_COMMANDS = ['tunnel', 'serve-web'] as const; + export const OPTIONS: OptionDescriptions> = { 'tunnel': { type: 'subcommand', @@ -66,6 +68,15 @@ export const OPTIONS: OptionDescriptions> = { } } }, + 'serve-web': { + type: 'subcommand', + description: 'Make the current machine accessible from vscode.dev or other machines through a secure tunnel', + options: { + 'cli-data-dir': { type: 'string', args: 'dir', description: localize('cliDataDir', "Directory where CLI metadata should be stored.") }, + 'disable-telemetry': { type: 'boolean' }, + 'telemetry-level': { type: 'string' }, + } + }, 'diff': { type: 'boolean', cat: 'o', alias: 'd', args: ['file', 'file'], description: localize('diff', "Compare two files with each other.") }, 'merge': { type: 'boolean', cat: 'o', alias: 'm', args: ['path1', 'path2', 'base', 'result'], description: localize('merge', "Perform a three-way merge by providing paths for two modified versions of a file, the common origin of both modified versions and the output file to save merge results.") }, diff --git a/src/vs/platform/environment/node/argvHelper.ts b/src/vs/platform/environment/node/argvHelper.ts index 74a7369225d..d8cefb6df67 100644 --- a/src/vs/platform/environment/node/argvHelper.ts +++ b/src/vs/platform/environment/node/argvHelper.ts @@ -7,7 +7,7 @@ import * as assert from 'assert'; import { IProcessEnvironment } from 'vs/base/common/platform'; import { localize } from 'vs/nls'; import { NativeParsedArgs } from 'vs/platform/environment/common/argv'; -import { ErrorReporter, OPTIONS, parseArgs } from 'vs/platform/environment/node/argv'; +import { ErrorReporter, NATIVE_CLI_COMMANDS, OPTIONS, parseArgs } from 'vs/platform/environment/node/argv'; function parseAndValidate(cmdLineArgs: string[], reportWarnings: boolean): NativeParsedArgs { const onMultipleValues = (id: string, val: string) => { @@ -21,14 +21,14 @@ function parseAndValidate(cmdLineArgs: string[], reportWarnings: boolean): Nativ }; const getSubcommandReporter = (command: string) => ({ onUnknownOption: (id: string) => { - if (command !== 'tunnel') { + if (!(NATIVE_CLI_COMMANDS as readonly string[]).includes(command)) { console.warn(localize('unknownSubCommandOption', "Warning: '{0}' is not in the list of known options for subcommand '{1}'", id, command)); } }, onMultipleValues, onEmptyValue, onDeprecatedOption, - getSubcommandReporter: command !== 'tunnel' ? getSubcommandReporter : undefined + getSubcommandReporter: (NATIVE_CLI_COMMANDS as readonly string[]).includes(command) ? getSubcommandReporter : undefined }); const errorReporter: ErrorReporter = { onUnknownOption: (id) => { From 6408ba941f7e961e00eb7a4cc66745894127ab03 Mon Sep 17 00:00:00 2001 From: Henning Dieterichs Date: Tue, 22 Aug 2023 17:50:58 +0200 Subject: [PATCH 113/221] fixes https://github.com/microsoft/vscode/issues/190961, fixes https://github.com/microsoft/vscode/issues/190959 --- .../diff/algorithms/joinSequenceDiffs.ts | 23 +++++++++++++++++++ .../advanced.expected.diff.json | 4 ++-- .../advanced.expected.diff.json | 4 ++-- .../noise-1/advanced.expected.diff.json | 4 ++-- .../ts-class/advanced.expected.diff.json | 4 ++-- .../advanced.expected.diff.json | 12 +++++----- .../ts-example1/advanced.expected.diff.json | 4 ++-- .../advanced.expected.diff.json | 4 ++-- .../ws-alignment/advanced.expected.diff.json | 4 ++-- 9 files changed, 43 insertions(+), 20 deletions(-) diff --git a/src/vs/editor/common/diff/algorithms/joinSequenceDiffs.ts b/src/vs/editor/common/diff/algorithms/joinSequenceDiffs.ts index b76c82d371b..c79d557e409 100644 --- a/src/vs/editor/common/diff/algorithms/joinSequenceDiffs.ts +++ b/src/vs/editor/common/diff/algorithms/joinSequenceDiffs.ts @@ -149,6 +149,29 @@ export function removeRandomMatches(sequence1: LinesSliceCharSequence, sequence2 diffs = result; } while (counter++ < 10 && shouldRepeat); + // Remove short suffixes/prefixes + for (let i = 0; i < diffs.length; i++) { + const cur = diffs[i]; + + let range1 = cur.seq1Range; + let range2 = cur.seq2Range; + + const fullRange1 = sequence1.extendToFullLines(cur.seq1Range); + const prefix = sequence1.getText(new OffsetRange(fullRange1.start, cur.seq1Range.start)); + if (prefix.length > 0 && prefix.trim().length <= 3 && cur.seq1Range.length + cur.seq2Range.length > 100) { + range1 = cur.seq1Range.deltaStart(-prefix.length); + range2 = cur.seq2Range.deltaStart(-prefix.length); + } + + const suffix = sequence1.getText(new OffsetRange(cur.seq1Range.endExclusive, fullRange1.endExclusive)); + if (suffix.length > 0 && (suffix.trim().length <= 3 && cur.seq1Range.length + cur.seq2Range.length > 150)) { + range1 = range1.deltaEnd(suffix.length); + range2 = range2.deltaEnd(suffix.length); + } + + diffs[i] = new SequenceDiff(range1, range2); + } + return diffs; } diff --git a/src/vs/editor/test/node/diffing/fixtures/class-replacement/advanced.expected.diff.json b/src/vs/editor/test/node/diffing/fixtures/class-replacement/advanced.expected.diff.json index 2b8f1b4ab1a..5cbd3c45666 100644 --- a/src/vs/editor/test/node/diffing/fixtures/class-replacement/advanced.expected.diff.json +++ b/src/vs/editor/test/node/diffing/fixtures/class-replacement/advanced.expected.diff.json @@ -13,8 +13,8 @@ "modifiedRange": "[29,37)", "innerChanges": [ { - "originalRange": "[29,1 -> 60,48]", - "modifiedRange": "[29,1 -> 36,66]" + "originalRange": "[29,1 -> 61,1]", + "modifiedRange": "[29,1 -> 37,1]" } ] }, diff --git a/src/vs/editor/test/node/diffing/fixtures/method-splitting/advanced.expected.diff.json b/src/vs/editor/test/node/diffing/fixtures/method-splitting/advanced.expected.diff.json index 8ac0682b508..b1de25a5907 100644 --- a/src/vs/editor/test/node/diffing/fixtures/method-splitting/advanced.expected.diff.json +++ b/src/vs/editor/test/node/diffing/fixtures/method-splitting/advanced.expected.diff.json @@ -13,8 +13,8 @@ "modifiedRange": "[6,11)", "innerChanges": [ { - "originalRange": "[6,2 -> 11,49]", - "modifiedRange": "[6,2 -> 6,91]" + "originalRange": "[6,1 -> 11,49]", + "modifiedRange": "[6,1 -> 6,91]" }, { "originalRange": "[12,76 -> 12,76]", diff --git a/src/vs/editor/test/node/diffing/fixtures/noise-1/advanced.expected.diff.json b/src/vs/editor/test/node/diffing/fixtures/noise-1/advanced.expected.diff.json index 5a679831447..20190a83798 100644 --- a/src/vs/editor/test/node/diffing/fixtures/noise-1/advanced.expected.diff.json +++ b/src/vs/editor/test/node/diffing/fixtures/noise-1/advanced.expected.diff.json @@ -21,8 +21,8 @@ "modifiedRange": "[53,6 -> 53,45]" }, { - "originalRange": "[52,77 -> 55,53]", - "modifiedRange": "[53,98 -> 65,66]" + "originalRange": "[52,77 -> 56,1]", + "modifiedRange": "[53,98 -> 66,1]" } ] } diff --git a/src/vs/editor/test/node/diffing/fixtures/ts-class/advanced.expected.diff.json b/src/vs/editor/test/node/diffing/fixtures/ts-class/advanced.expected.diff.json index 92f5e20707f..0b00ea98beb 100644 --- a/src/vs/editor/test/node/diffing/fixtures/ts-class/advanced.expected.diff.json +++ b/src/vs/editor/test/node/diffing/fixtures/ts-class/advanced.expected.diff.json @@ -47,8 +47,8 @@ "modifiedRange": "[8,12)", "innerChanges": [ { - "originalRange": "[11,10 -> 20,25]", - "modifiedRange": "[8,10 -> 11,51]" + "originalRange": "[11,10 -> 21,1]", + "modifiedRange": "[8,10 -> 12,1]" } ] }, diff --git a/src/vs/editor/test/node/diffing/fixtures/ts-confusing-2/advanced.expected.diff.json b/src/vs/editor/test/node/diffing/fixtures/ts-confusing-2/advanced.expected.diff.json index f6817defb49..3835a5ceb3c 100644 --- a/src/vs/editor/test/node/diffing/fixtures/ts-confusing-2/advanced.expected.diff.json +++ b/src/vs/editor/test/node/diffing/fixtures/ts-confusing-2/advanced.expected.diff.json @@ -43,8 +43,8 @@ "modifiedRange": "[14,18)", "innerChanges": [ { - "originalRange": "[14,120 -> 14,211]", - "modifiedRange": "[14,120 -> 17,1]" + "originalRange": "[14,120 -> 15,1]", + "modifiedRange": "[14,120 -> 18,1]" } ] }, @@ -65,8 +65,8 @@ "modifiedRange": "[21,18 -> 21,43]" }, { - "originalRange": "[17,71 -> 23,4]", - "modifiedRange": "[21,74 -> 21,81]" + "originalRange": "[17,71 -> 24,1]", + "modifiedRange": "[21,74 -> 22,1]" } ] }, @@ -93,8 +93,8 @@ "modifiedRange": "[26,38)", "innerChanges": [ { - "originalRange": "[28,1 -> 30,31]", - "modifiedRange": "[26,1 -> 37,9]" + "originalRange": "[28,1 -> 31,1]", + "modifiedRange": "[26,1 -> 38,1]" } ] } diff --git a/src/vs/editor/test/node/diffing/fixtures/ts-example1/advanced.expected.diff.json b/src/vs/editor/test/node/diffing/fixtures/ts-example1/advanced.expected.diff.json index d8eac8523e6..c7cd88a788b 100644 --- a/src/vs/editor/test/node/diffing/fixtures/ts-example1/advanced.expected.diff.json +++ b/src/vs/editor/test/node/diffing/fixtures/ts-example1/advanced.expected.diff.json @@ -27,8 +27,8 @@ "modifiedRange": "[17,80)", "innerChanges": [ { - "originalRange": "[13,10 -> 14,43]", - "modifiedRange": "[17,10 -> 79,2]" + "originalRange": "[13,10 -> 15,1]", + "modifiedRange": "[17,10 -> 80,1]" } ] } diff --git a/src/vs/editor/test/node/diffing/fixtures/ts-too-much-minimization/advanced.expected.diff.json b/src/vs/editor/test/node/diffing/fixtures/ts-too-much-minimization/advanced.expected.diff.json index aa65f823a85..7a52e0e84aa 100644 --- a/src/vs/editor/test/node/diffing/fixtures/ts-too-much-minimization/advanced.expected.diff.json +++ b/src/vs/editor/test/node/diffing/fixtures/ts-too-much-minimization/advanced.expected.diff.json @@ -13,8 +13,8 @@ "modifiedRange": "[9,15)", "innerChanges": [ { - "originalRange": "[9,124 -> 9,124]", - "modifiedRange": "[9,124 -> 14,143]" + "originalRange": "[9,124 -> 10,1]", + "modifiedRange": "[9,124 -> 15,1]" } ] } diff --git a/src/vs/editor/test/node/diffing/fixtures/ws-alignment/advanced.expected.diff.json b/src/vs/editor/test/node/diffing/fixtures/ws-alignment/advanced.expected.diff.json index 85a9a2fe928..66e738ab041 100644 --- a/src/vs/editor/test/node/diffing/fixtures/ws-alignment/advanced.expected.diff.json +++ b/src/vs/editor/test/node/diffing/fixtures/ws-alignment/advanced.expected.diff.json @@ -23,8 +23,8 @@ "modifiedRange": "[7,18)", "innerChanges": [ { - "originalRange": "[7,5 -> 12,17]", - "modifiedRange": "[7,5 -> 16,7]" + "originalRange": "[7,1 -> 13,1]", + "modifiedRange": "[7,1 -> 17,1]" }, { "originalRange": "[13,6 -> 13,11]", From 2cfdb5302a4e23cf51903b4e7df1875a5d611b6d Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Wed, 23 Aug 2023 11:50:46 +0200 Subject: [PATCH 114/221] fix #189138 (#191051) * fix #189138 * feedback --- .../services/configuration/browser/configuration.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/services/configuration/browser/configuration.ts b/src/vs/workbench/services/configuration/browser/configuration.ts index 8f942efdd0e..591bddbe576 100644 --- a/src/vs/workbench/services/configuration/browser/configuration.ts +++ b/src/vs/workbench/services/configuration/browser/configuration.ts @@ -259,8 +259,8 @@ class FileServiceBasedConfiguration extends Disposable { const resolveContents = async (resources: URI[]): Promise<(string | undefined)[]> => { return Promise.all(resources.map(async resource => { try { - const content = (await this.fileService.readFile(resource)).value.toString(); - return content; + const content = await this.fileService.readFile(resource, { atomic: true }); + return content.value.toString(); } catch (error) { this.logService.trace(`Error while resolving configuration file '${resource.toString()}': ${errors.getErrorMessage(error)}`); if ((error).fileOperationResult !== FileOperationResult.FILE_NOT_FOUND @@ -494,7 +494,7 @@ class FileServiceBasedRemoteUserConfiguration extends Disposable { } async resolveContent(): Promise { - const content = await this.fileService.readFile(this.configurationResource); + const content = await this.fileService.readFile(this.configurationResource, { atomic: true }); return content.value.toString(); } @@ -764,7 +764,7 @@ class FileServiceBasedWorkspaceConfiguration extends Disposable { } async resolveContent(workspaceIdentifier: IWorkspaceIdentifier): Promise { - const content = await this.fileService.readFile(workspaceIdentifier.configPath); + const content = await this.fileService.readFile(workspaceIdentifier.configPath, { atomic: true }); return content.value.toString(); } From 3e9a48f4888bd51b524e40de18efe255242bff09 Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Wed, 23 Aug 2023 02:52:31 -0700 Subject: [PATCH 115/221] eng: reapply test leak fixes (#190890) * eng: reapply test leak fixes Re-applies #190623 which I merged before everyone had a chance to review. Alex and Ben, you were the two people whose code this touches and didn't review it in the original PR. * :lipstick: * fix merge * better handling of editor listeners --------- Co-authored-by: Benjamin Pasero --- src/vs/base/browser/ui/grid/gridview.ts | 1 + src/vs/base/browser/ui/splitview/splitview.ts | 4 +-- src/vs/base/browser/ui/toolbar/toolbar.ts | 2 +- .../diffEditorWidget2/diffEditorEditors.ts | 4 +-- .../suggest/browser/suggestController.ts | 2 +- src/vs/platform/actions/browser/buttonbar.ts | 2 +- src/vs/workbench/browser/dnd.ts | 5 ++-- .../browser/parts/editor/editorGroupView.ts | 2 +- .../parts/editor/editorGroupWatermark.ts | 2 +- .../browser/parts/editor/tabsTitleControl.ts | 10 +++---- .../common/editor/editorGroupModel.ts | 11 ++++++++ .../browser/editors/textFileEditorTracker.ts | 2 +- .../browser/textFileEditorTracker.test.ts | 3 +++ .../browser/inlineChatController.ts | 3 ++- .../inlineChat/browser/inlineChatSession.ts | 2 ++ .../inlineChat/browser/inlineChatWidget.ts | 8 +++--- .../test/browser/inlineChatController.test.ts | 26 +++++-------------- .../markers/test/browser/markersModel.test.ts | 3 +++ .../editor/browser/codeEditorService.ts | 4 +-- .../services/editor/browser/editorService.ts | 6 ++--- .../browser/browserTextFileService.ts | 2 +- .../textfile/browser/textFileService.ts | 4 ++- .../common/textFileSaveParticipant.ts | 6 ++++- .../test/browser/textFileEditorModel.test.ts | 6 ++--- .../storedFileWorkingCopySaveParticipant.ts | 2 ++ .../workingCopyFileOperationParticipant.ts | 2 ++ .../test/browser/workbenchTestServices.ts | 13 +++++----- 27 files changed, 78 insertions(+), 59 deletions(-) diff --git a/src/vs/base/browser/ui/grid/gridview.ts b/src/vs/base/browser/ui/grid/gridview.ts index c89c6a7a063..9445c64286a 100644 --- a/src/vs/base/browser/ui/grid/gridview.ts +++ b/src/vs/base/browser/ui/grid/gridview.ts @@ -705,6 +705,7 @@ class BranchNode implements ISplitView, IDisposable { this.splitviewSashResetDisposable.dispose(); this.childrenSashResetDisposable.dispose(); this.childrenChangeDisposable.dispose(); + this.onDidScrollDisposable.dispose(); this.splitview.dispose(); } } diff --git a/src/vs/base/browser/ui/splitview/splitview.ts b/src/vs/base/browser/ui/splitview/splitview.ts index b822db43751..28f18d42537 100644 --- a/src/vs/base/browser/ui/splitview/splitview.ts +++ b/src/vs/base/browser/ui/splitview/splitview.ts @@ -565,11 +565,11 @@ export class SplitView extends Disposable { this.sashContainer = append(this.el, $('.sash-container')); this.viewContainer = $('.split-view-container'); - this.scrollable = new Scrollable({ + this.scrollable = this._register(new Scrollable({ forceIntegerValues: true, smoothScrollDuration: 125, scheduleAtNextAnimationFrame - }); + })); this.scrollableElement = this._register(new SmoothScrollableElement(this.viewContainer, { vertical: this.orientation === Orientation.VERTICAL ? (options.scrollbarVisibility ?? ScrollbarVisibility.Auto) : ScrollbarVisibility.Hidden, horizontal: this.orientation === Orientation.HORIZONTAL ? (options.scrollbarVisibility ?? ScrollbarVisibility.Auto) : ScrollbarVisibility.Hidden diff --git a/src/vs/base/browser/ui/toolbar/toolbar.ts b/src/vs/base/browser/ui/toolbar/toolbar.ts index 1a6089b5958..bcb90361b41 100644 --- a/src/vs/base/browser/ui/toolbar/toolbar.ts +++ b/src/vs/base/browser/ui/toolbar/toolbar.ts @@ -52,7 +52,7 @@ export class ToolBar extends Disposable { private _onDidChangeDropdownVisibility = this._register(new EventMultiplexer()); readonly onDidChangeDropdownVisibility = this._onDidChangeDropdownVisibility.event; - private disposables = new DisposableStore(); + private disposables = this._register(new DisposableStore()); constructor(container: HTMLElement, contextMenuProvider: IContextMenuProvider, options: IToolBarOptions = { orientation: ActionsOrientation.HORIZONTAL }) { super(); diff --git a/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorEditors.ts b/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorEditors.ts index cce99a94271..ee764c81aed 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorEditors.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorEditors.ts @@ -35,8 +35,8 @@ export class DiffEditorEditors extends Disposable { ) { super(); - this.original = this._createLeftHandSideEditor(_options.editorOptions.get(), codeEditorWidgetOptions.originalEditor || {}); - this.modified = this._createRightHandSideEditor(_options.editorOptions.get(), codeEditorWidgetOptions.modifiedEditor || {}); + this.original = this._register(this._createLeftHandSideEditor(_options.editorOptions.get(), codeEditorWidgetOptions.originalEditor || {})); + this.modified = this._register(this._createRightHandSideEditor(_options.editorOptions.get(), codeEditorWidgetOptions.modifiedEditor || {})); this._register(autorunHandleChanges({ createEmptyChangeSummary: () => ({} as IDiffEditorConstructionOptions), diff --git a/src/vs/editor/contrib/suggest/browser/suggestController.ts b/src/vs/editor/contrib/suggest/browser/suggestController.ts index 887fb23cb2d..6450e989bce 100644 --- a/src/vs/editor/contrib/suggest/browser/suggestController.ts +++ b/src/vs/editor/contrib/suggest/browser/suggestController.ts @@ -143,7 +143,7 @@ export class SuggestController implements IEditorContribution { // context key: update insert/replace mode const ctxInsertMode = SuggestContext.InsertMode.bindTo(_contextKeyService); ctxInsertMode.set(editor.getOption(EditorOption.suggest).insertMode); - this.model.onDidTrigger(() => ctxInsertMode.set(editor.getOption(EditorOption.suggest).insertMode)); + this._toDispose.add(this.model.onDidTrigger(() => ctxInsertMode.set(editor.getOption(EditorOption.suggest).insertMode))); this.widget = this._toDispose.add(new IdleValue(() => { diff --git a/src/vs/platform/actions/browser/buttonbar.ts b/src/vs/platform/actions/browser/buttonbar.ts index cb6ab4c31df..4965d6bb5cd 100644 --- a/src/vs/platform/actions/browser/buttonbar.ts +++ b/src/vs/platform/actions/browser/buttonbar.ts @@ -55,7 +55,7 @@ export class MenuWorkbenchButtonBar extends ButtonBar { 'workbenchActionExecuted', { id: e.action.id, from: options.telemetrySource! } ); - }, this._store); + }, undefined, this._store); } const conifgProvider: IButtonConfigProvider = options?.buttonConfigProvider ?? (() => ({ showLabel: true })); diff --git a/src/vs/workbench/browser/dnd.ts b/src/vs/workbench/browser/dnd.ts index c196ac2132e..52afb8083d8 100644 --- a/src/vs/workbench/browser/dnd.ts +++ b/src/vs/workbench/browser/dnd.ts @@ -12,7 +12,7 @@ import { ITreeDragOverReaction } from 'vs/base/browser/ui/tree/tree'; import { coalesce } from 'vs/base/common/arrays'; import { UriList, VSDataTransfer } from 'vs/base/common/dataTransfer'; import { Emitter } from 'vs/base/common/event'; -import { Disposable, DisposableStore, IDisposable } from 'vs/base/common/lifecycle'; +import { Disposable, DisposableStore, IDisposable, markAsSingleton } from 'vs/base/common/lifecycle'; import { stringify } from 'vs/base/common/marshalling'; import { Mimes } from 'vs/base/common/mime'; import { FileAccess, Schemas } from 'vs/base/common/network'; @@ -427,6 +427,7 @@ export class CompositeDragAndDropObserver extends Disposable { static get INSTANCE(): CompositeDragAndDropObserver { if (!CompositeDragAndDropObserver.instance) { CompositeDragAndDropObserver.instance = new CompositeDragAndDropObserver(); + markAsSingleton(CompositeDragAndDropObserver.instance); } return CompositeDragAndDropObserver.instance; @@ -523,7 +524,7 @@ export class CompositeDragAndDropObserver extends Disposable { if (callbacks.onDragEnd) { this.onDragEnd.event(e => { callbacks.onDragEnd!(e); - }); + }, this, disposableStore); } return this._register(disposableStore); diff --git a/src/vs/workbench/browser/parts/editor/editorGroupView.ts b/src/vs/workbench/browser/parts/editor/editorGroupView.ts index c80fa632d3e..01b92a4b7e2 100644 --- a/src/vs/workbench/browser/parts/editor/editorGroupView.ts +++ b/src/vs/workbench/browser/parts/editor/editorGroupView.ts @@ -244,7 +244,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView { const groupEditorsCountContext = EditorGroupEditorsCountContext.bindTo(this.scopedContextKeyService); const groupLockedContext = ActiveEditorGroupLockedContext.bindTo(this.scopedContextKeyService); - const activeEditorListener = new MutableDisposable(); + const activeEditorListener = this._register(new MutableDisposable()); const observeActiveEditor = () => { activeEditorListener.clear(); diff --git a/src/vs/workbench/browser/parts/editor/editorGroupWatermark.ts b/src/vs/workbench/browser/parts/editor/editorGroupWatermark.ts index 55d6506abab..ff8a2778c7c 100644 --- a/src/vs/workbench/browser/parts/editor/editorGroupWatermark.ts +++ b/src/vs/workbench/browser/parts/editor/editorGroupWatermark.ts @@ -90,7 +90,7 @@ export class EditorGroupWatermark extends Disposable { } private registerListeners(): void { - this.lifecycleService.onDidShutdown(() => this.dispose()); + this._register(this.lifecycleService.onDidShutdown(() => this.dispose())); this._register(this.configurationService.onDidChangeConfiguration(e => { if (e.affectsConfiguration('workbench.tips.enabled')) { diff --git a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts index d712b1a146b..3272b3e4839 100644 --- a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts +++ b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts @@ -184,7 +184,7 @@ export class TabsTitleControl extends TitleControl { this.updateTabSizing(false); // Tabs Scrollbar - this.tabsScrollbar = this._register(this.createTabsScrollbar(this.tabsContainer)); + this.tabsScrollbar = this.createTabsScrollbar(this.tabsContainer); this.tabsAndActionsContainer.appendChild(this.tabsScrollbar.getDomNode()); // Tabs Container listeners @@ -206,19 +206,19 @@ export class TabsTitleControl extends TitleControl { } private createTabsScrollbar(scrollable: HTMLElement): ScrollableElement { - const tabsScrollbar = new ScrollableElement(scrollable, { + const tabsScrollbar = this._register(new ScrollableElement(scrollable, { horizontal: ScrollbarVisibility.Auto, horizontalScrollbarSize: this.getTabsScrollbarSizing(), vertical: ScrollbarVisibility.Hidden, scrollYToX: true, useShadows: false - }); + })); - tabsScrollbar.onScroll(e => { + this._register(tabsScrollbar.onScroll(e => { if (e.scrollLeftChanged) { scrollable.scrollLeft = e.scrollLeft; } - }); + })); return tabsScrollbar; } diff --git a/src/vs/workbench/common/editor/editorGroupModel.ts b/src/vs/workbench/common/editor/editorGroupModel.ts index 7fc1ae6cbc0..8e3c7b7a811 100644 --- a/src/vs/workbench/common/editor/editorGroupModel.ts +++ b/src/vs/workbench/common/editor/editorGroupModel.ts @@ -180,6 +180,8 @@ export class EditorGroupModel extends Disposable { private editors: EditorInput[] = []; private mru: EditorInput[] = []; + private readonly editorListeners = new Set(); + private locked = false; private preview: EditorInput | null = null; // editor in preview state @@ -405,6 +407,7 @@ export class EditorGroupModel extends Disposable { private registerEditorListeners(editor: EditorInput): void { const listeners = new DisposableStore(); + this.editorListeners.add(listeners); // Re-emit disposal of editor input as our own event listeners.add(Event.once(editor.onWillDispose)(() => { @@ -453,6 +456,7 @@ export class EditorGroupModel extends Disposable { listeners.add(this.onDidModelChange(event => { if (event.kind === GroupModelChangeKind.EDITOR_CLOSE && event.editor?.matches(editor)) { dispose(listeners); + this.editorListeners.delete(listeners); } })); } @@ -1077,4 +1081,11 @@ export class EditorGroupModel extends Disposable { return this._id; } + + override dispose(): void { + dispose(Array.from(this.editorListeners)); + this.editorListeners.clear(); + + super.dispose(); + } } diff --git a/src/vs/workbench/contrib/files/browser/editors/textFileEditorTracker.ts b/src/vs/workbench/contrib/files/browser/editors/textFileEditorTracker.ts index fb876ba670a..afa94056cd5 100644 --- a/src/vs/workbench/contrib/files/browser/editors/textFileEditorTracker.ts +++ b/src/vs/workbench/contrib/files/browser/editors/textFileEditorTracker.ts @@ -47,7 +47,7 @@ export class TextFileEditorTracker extends Disposable implements IWorkbenchContr this._register(this.hostService.onDidChangeFocus(hasFocus => hasFocus ? this.reloadVisibleTextFileEditors() : undefined)); // Lifecycle - this.lifecycleService.onDidShutdown(() => this.dispose()); + this._register(this.lifecycleService.onDidShutdown(() => this.dispose())); } //#region Text File: Ensure every dirty text and untitled file is opened in an editor diff --git a/src/vs/workbench/contrib/files/test/browser/textFileEditorTracker.test.ts b/src/vs/workbench/contrib/files/test/browser/textFileEditorTracker.test.ts index bc69b29a381..b0afe7cc554 100644 --- a/src/vs/workbench/contrib/files/test/browser/textFileEditorTracker.test.ts +++ b/src/vs/workbench/contrib/files/test/browser/textFileEditorTracker.test.ts @@ -77,6 +77,7 @@ suite('Files - TextFileEditorTracker', () => { instantiationService.stub(IWorkspaceTrustRequestService, new TestWorkspaceTrustRequestService(false)); const editorService: EditorService = instantiationService.createInstance(EditorService); + disposables.add(editorService); instantiationService.stub(IEditorService, editorService); const accessor = instantiationService.createInstance(TestServiceAccessor); @@ -93,6 +94,7 @@ suite('Files - TextFileEditorTracker', () => { const resource = toResource.call(this, '/path/index.txt'); const model = await accessor.textFileService.files.resolve(resource) as IResolvedTextFileEditorModel; + disposables.add(model); model.textEditorModel.setValue('Super Good'); assert.strictEqual(snapshotToString(model.createSnapshot()!), 'Super Good'); @@ -141,6 +143,7 @@ suite('Files - TextFileEditorTracker', () => { } const model = await accessor.textFileService.files.resolve(resource) as IResolvedTextFileEditorModel; + disposables.add(model); model.textEditorModel.setValue('Super Good'); diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts index 104830cc852..f91de7e3ee8 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts @@ -100,7 +100,7 @@ export class InlineChatController implements IEditorContribution { private _messages = this._store.add(new Emitter()); - private readonly _sessionStore: DisposableStore = new DisposableStore(); + private readonly _sessionStore: DisposableStore = this._store.add(new DisposableStore()); private readonly _stashedSession: MutableDisposable = this._store.add(new MutableDisposable()); private _activeSession?: Session; private _strategy?: EditModeStrategy; @@ -146,6 +146,7 @@ export class InlineChatController implements IEditorContribution { } dispose(): void { + this._strategy?.dispose(); this._stashedSession.clear(); this.finishExistingSession(); this._store.dispose(); diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatSession.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatSession.ts index 434aea1f4d2..fcbb998dc79 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatSession.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatSession.ts @@ -385,6 +385,8 @@ export interface IInlineChatSessionService { // recordings(): readonly Recording[]; + + dispose(): void; } type SessionData = { diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts index 31d9fa9c36b..343749ce5c6 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts @@ -230,7 +230,7 @@ export class InlineChatWidget { })); const uri = URI.from({ scheme: 'vscode', authority: 'inline-chat', path: `/inline-chat/model${InlineChatWidget._modelPool++}.txt` }); - this._inputModel = this._modelService.getModel(uri) ?? this._modelService.createModel('', null, uri); + this._inputModel = this._store.add(this._modelService.getModel(uri) ?? this._modelService.createModel('', null, uri)); this._inputEditor.setModel(this._inputModel); // --- context keys @@ -359,13 +359,13 @@ export class InlineChatWidget { this._store.add(feedbackToolbar); // preview editors - this._previewDiffEditor = new IdleValue(() => this._store.add(_instantiationService.createInstance(EmbeddedDiffEditorWidget2, this._elements.previewDiff, { + this._previewDiffEditor = this._store.add(new IdleValue(() => this._store.add(_instantiationService.createInstance(EmbeddedDiffEditorWidget2, this._elements.previewDiff, { ..._previewEditorEditorOptions, onlyShowAccessibleDiffViewer: this._accessibilityService.isScreenReaderOptimized(), - }, { modifiedEditor: codeEditorWidgetOptions, originalEditor: codeEditorWidgetOptions }, parentEditor))); + }, { modifiedEditor: codeEditorWidgetOptions, originalEditor: codeEditorWidgetOptions }, parentEditor)))); this._previewCreateTitle = this._store.add(_instantiationService.createInstance(ResourceLabel, this._elements.previewCreateTitle, { supportIcons: true })); - this._previewCreateEditor = new IdleValue(() => this._store.add(_instantiationService.createInstance(EmbeddedCodeEditorWidget, this._elements.previewCreate, _previewEditorEditorOptions, codeEditorWidgetOptions, parentEditor))); + this._previewCreateEditor = this._store.add(new IdleValue(() => this._store.add(_instantiationService.createInstance(EmbeddedCodeEditorWidget, this._elements.previewCreate, _previewEditorEditorOptions, codeEditorWidgetOptions, parentEditor)))); this._elements.message.tabIndex = 0; this._elements.message.ariaLabel = this._accessibleViewService.getOpenAriaHint(AccessibilityVerbositySettingId.InlineChat); diff --git a/src/vs/workbench/contrib/inlineChat/test/browser/inlineChatController.test.ts b/src/vs/workbench/contrib/inlineChat/test/browser/inlineChatController.test.ts index ab5e4b27e1b..7a9beea7519 100644 --- a/src/vs/workbench/contrib/inlineChat/test/browser/inlineChatController.test.ts +++ b/src/vs/workbench/contrib/inlineChat/test/browser/inlineChatController.test.ts @@ -24,7 +24,6 @@ import { IEditorProgressService, IProgressRunner } from 'vs/platform/progress/co import { mock } from 'vs/base/test/common/mock'; import { Emitter, Event } from 'vs/base/common/event'; import { equals } from 'vs/base/common/arrays'; -import { timeout } from 'vs/base/common/async'; import { IChatAccessibilityService } from 'vs/workbench/contrib/chat/browser/chat'; import { IChatResponseViewModel } from 'vs/workbench/contrib/chat/common/chatViewModel'; import { IAccessibleViewService } from 'vs/workbench/contrib/accessibility/browser/accessibleView'; @@ -114,11 +113,11 @@ suite('InteractiveChatController', function () { }] ); - instaService = workbenchInstantiationService(undefined, store).createChild(serviceCollection); - inlineChatSessionService = instaService.get(IInlineChatSessionService); + instaService = store.add(workbenchInstantiationService(undefined, store).createChild(serviceCollection)); + inlineChatSessionService = store.add(instaService.get(IInlineChatSessionService)); - model = instaService.get(IModelService).createModel('Hello\nWorld\nHello Again\nHello World\n', null); - editor = instantiateTestCodeEditor(instaService, model); + model = store.add(instaService.get(IModelService).createModel('Hello\nWorld\nHello Again\nHello World\n', null)); + editor = store.add(instantiateTestCodeEditor(instaService, model)); store.add(inlineChatService.addProvider({ debugName: 'Unit Test', @@ -142,8 +141,6 @@ suite('InteractiveChatController', function () { }); teardown(function () { - editor.dispose(); - model.dispose(); store.clear(); ctrl?.dispose(); }); @@ -295,19 +292,8 @@ suite('InteractiveChatController', function () { wholeRange: new Range(3, 1, 3, 3) }; }, - async provideResponse(session, request) { - - // SLOW response - await timeout(50000); - - return { - type: InlineChatResponseType.EditorEdit, - id: Math.random(), - edits: [{ - range: new Range(1, 1, 1, 1), // EDIT happens outside of whole range - text: `${request.prompt}\n${request.prompt}` - }] - }; + provideResponse(session, request) { + return new Promise(() => { }); } }); store.add(d); diff --git a/src/vs/workbench/contrib/markers/test/browser/markersModel.test.ts b/src/vs/workbench/contrib/markers/test/browser/markersModel.test.ts index 9cb2c9dc650..b8334c948d6 100644 --- a/src/vs/workbench/contrib/markers/test/browser/markersModel.test.ts +++ b/src/vs/workbench/contrib/markers/test/browser/markersModel.test.ts @@ -8,6 +8,7 @@ import { URI } from 'vs/base/common/uri'; import { IMarker, MarkerSeverity, IRelatedInformation } from 'vs/platform/markers/common/markers'; import { MarkersModel, Marker, ResourceMarkers, RelatedInformation } from 'vs/workbench/contrib/markers/browser/markersModel'; import { groupBy } from 'vs/base/common/collections'; +import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils'; class TestMarkersModel extends MarkersModel { @@ -27,6 +28,8 @@ class TestMarkersModel extends MarkersModel { suite('MarkersModel Test', () => { + ensureNoDisposablesAreLeakedInTestSuite(); + test('marker ids are unique', function () { const marker1 = anErrorWithRange(3); const marker2 = anErrorWithRange(3); diff --git a/src/vs/workbench/services/editor/browser/codeEditorService.ts b/src/vs/workbench/services/editor/browser/codeEditorService.ts index 657f203312c..9930f85f58c 100644 --- a/src/vs/workbench/services/editor/browser/codeEditorService.ts +++ b/src/vs/workbench/services/editor/browser/codeEditorService.ts @@ -25,8 +25,8 @@ export class CodeEditorService extends AbstractCodeEditorService { ) { super(themeService); - this.registerCodeEditorOpenHandler(this.doOpenCodeEditor.bind(this)); - this.registerCodeEditorOpenHandler(this.doOpenCodeEditorFromDiff.bind(this)); + this._register(this.registerCodeEditorOpenHandler(this.doOpenCodeEditor.bind(this))); + this._register(this.registerCodeEditorOpenHandler(this.doOpenCodeEditorFromDiff.bind(this))); } getActiveCodeEditor(): ICodeEditor | null { diff --git a/src/vs/workbench/services/editor/browser/editorService.ts b/src/vs/workbench/services/editor/browser/editorService.ts index e241e493f65..f997b3ecfbd 100644 --- a/src/vs/workbench/services/editor/browser/editorService.ts +++ b/src/vs/workbench/services/editor/browser/editorService.ts @@ -83,9 +83,9 @@ export class EditorService extends Disposable implements EditorServiceImpl { // Editor & group changes this.editorGroupService.whenReady.then(() => this.onEditorGroupsReady()); - this.editorGroupService.onDidChangeActiveGroup(group => this.handleActiveEditorChange(group)); - this.editorGroupService.onDidAddGroup(group => this.registerGroupListeners(group as IEditorGroupView)); - this.editorsObserver.onDidMostRecentlyActiveEditorsChange(() => this._onDidMostRecentlyActiveEditorsChange.fire()); + this._register(this.editorGroupService.onDidChangeActiveGroup(group => this.handleActiveEditorChange(group))); + this._register(this.editorGroupService.onDidAddGroup(group => this.registerGroupListeners(group as IEditorGroupView))); + this._register(this.editorsObserver.onDidMostRecentlyActiveEditorsChange(() => this._onDidMostRecentlyActiveEditorsChange.fire())); // Out of workspace file watchers this._register(this.onDidVisibleEditorsChange(() => this.handleVisibleEditorsChange())); diff --git a/src/vs/workbench/services/textfile/browser/browserTextFileService.ts b/src/vs/workbench/services/textfile/browser/browserTextFileService.ts index 78957c01afd..188ca299d5f 100644 --- a/src/vs/workbench/services/textfile/browser/browserTextFileService.ts +++ b/src/vs/workbench/services/textfile/browser/browserTextFileService.ts @@ -54,7 +54,7 @@ export class BrowserTextFileService extends AbstractTextFileService { private registerListeners(): void { // Lifecycle - this.lifecycleService.onBeforeShutdown(event => event.veto(this.onBeforeShutdown(), 'veto.textFiles')); + this._register(this.lifecycleService.onBeforeShutdown(event => event.veto(this.onBeforeShutdown(), 'veto.textFiles'))); } private onBeforeShutdown(): boolean { diff --git a/src/vs/workbench/services/textfile/browser/textFileService.ts b/src/vs/workbench/services/textfile/browser/textFileService.ts index 45015baa458..f7a87fb1b4b 100644 --- a/src/vs/workbench/services/textfile/browser/textFileService.ts +++ b/src/vs/workbench/services/textfile/browser/textFileService.ts @@ -89,7 +89,7 @@ export abstract class AbstractTextFileService extends Disposable implements ITex private provideDecorations(): void { // Text file model decorations - this.decorationsService.registerDecorationsProvider(new class extends Disposable implements IDecorationsProvider { + const provider = this._register(new class extends Disposable implements IDecorationsProvider { readonly label = localize('textFileModelDecorations', "Text File Model Decorations"); @@ -161,6 +161,8 @@ export abstract class AbstractTextFileService extends Disposable implements ITex return undefined; } }(this.files)); + + this._register(this.decorationsService.registerDecorationsProvider(provider)); } //#endregin diff --git a/src/vs/workbench/services/textfile/common/textFileSaveParticipant.ts b/src/vs/workbench/services/textfile/common/textFileSaveParticipant.ts index ab3cb0a0e8a..3dc16d1a46e 100644 --- a/src/vs/workbench/services/textfile/common/textFileSaveParticipant.ts +++ b/src/vs/workbench/services/textfile/common/textFileSaveParticipant.ts @@ -60,11 +60,15 @@ export class TextFileSaveParticipant extends Disposable { model.textEditorModel?.pushStackElement(); }, () => { // user cancel - cts.dispose(true); + cts.cancel(); + }).finally(() => { + cts.dispose(); }); } override dispose(): void { this.saveParticipants.splice(0, this.saveParticipants.length); + + super.dispose(); } } diff --git a/src/vs/workbench/services/textfile/test/browser/textFileEditorModel.test.ts b/src/vs/workbench/services/textfile/test/browser/textFileEditorModel.test.ts index 7595d417a5f..7ca2a09bfb1 100644 --- a/src/vs/workbench/services/textfile/test/browser/textFileEditorModel.test.ts +++ b/src/vs/workbench/services/textfile/test/browser/textFileEditorModel.test.ts @@ -548,7 +548,7 @@ suite('Files - TextFileEditorModel', () => { test('Update Dirty', async function () { let eventCounter = 0; - const model = instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/index_async.txt'), 'utf8', undefined); + const model: TextFileEditorModel = instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/index_async.txt'), 'utf8', undefined); model.setDirty(true); assert.ok(!model.isDirty()); // needs to be resolved @@ -638,8 +638,8 @@ suite('Files - TextFileEditorModel', () => { }); test('save() and isDirty() - proper with check for mtimes', async function () { - const input1 = createFileEditorInput(instantiationService, toResource.call(this, '/path/index_async2.txt')); - const input2 = createFileEditorInput(instantiationService, toResource.call(this, '/path/index_async.txt')); + const input1 = disposables.add(createFileEditorInput(instantiationService, toResource.call(this, '/path/index_async2.txt'))); + const input2 = disposables.add(createFileEditorInput(instantiationService, toResource.call(this, '/path/index_async.txt'))); const model1 = await input1.resolve() as TextFileEditorModel; const model2 = await input2.resolve() as TextFileEditorModel; diff --git a/src/vs/workbench/services/workingCopy/common/storedFileWorkingCopySaveParticipant.ts b/src/vs/workbench/services/workingCopy/common/storedFileWorkingCopySaveParticipant.ts index 18be856eb47..11bddb67625 100644 --- a/src/vs/workbench/services/workingCopy/common/storedFileWorkingCopySaveParticipant.ts +++ b/src/vs/workbench/services/workingCopy/common/storedFileWorkingCopySaveParticipant.ts @@ -69,5 +69,7 @@ export class StoredFileWorkingCopySaveParticipant extends Disposable { override dispose(): void { this.saveParticipants.splice(0, this.saveParticipants.length); + + super.dispose(); } } diff --git a/src/vs/workbench/services/workingCopy/common/workingCopyFileOperationParticipant.ts b/src/vs/workbench/services/workingCopy/common/workingCopyFileOperationParticipant.ts index e75246b8b83..f3f4dd8f05e 100644 --- a/src/vs/workbench/services/workingCopy/common/workingCopyFileOperationParticipant.ts +++ b/src/vs/workbench/services/workingCopy/common/workingCopyFileOperationParticipant.ts @@ -46,5 +46,7 @@ export class WorkingCopyFileOperationParticipant extends Disposable { override dispose(): void { this.participants.clear(); + + super.dispose(); } } diff --git a/src/vs/workbench/test/browser/workbenchTestServices.ts b/src/vs/workbench/test/browser/workbenchTestServices.ts index 0fffe75c46f..c566bc46401 100644 --- a/src/vs/workbench/test/browser/workbenchTestServices.ts +++ b/src/vs/workbench/test/browser/workbenchTestServices.ts @@ -283,15 +283,16 @@ export function workbenchInstantiationService( instantiationService.stub(IUndoRedoService, instantiationService.createInstance(UndoRedoService)); const themeService = new TestThemeService(); instantiationService.stub(IThemeService, themeService); - instantiationService.stub(ILanguageConfigurationService, new TestLanguageConfigurationService()); + instantiationService.stub(ILanguageConfigurationService, disposables.add(new TestLanguageConfigurationService())); instantiationService.stub(IModelService, disposables.add(instantiationService.createInstance(ModelService))); const fileService = overrides?.fileService ? overrides.fileService(instantiationService) : new TestFileService(); instantiationService.stub(IFileService, fileService); const uriIdentityService = new UriIdentityService(fileService); + disposables.add(uriIdentityService); instantiationService.stub(IFilesConfigurationService, disposables.add(new TestFilesConfigurationService(contextKeyService, configService, workspaceContextService, environmentService, uriIdentityService, fileService))); instantiationService.stub(IUriIdentityService, uriIdentityService); - const userDataProfilesService = instantiationService.stub(IUserDataProfilesService, new UserDataProfilesService(environmentService, fileService, uriIdentityService, new NullLogService())); - instantiationService.stub(IUserDataProfileService, new UserDataProfileService(userDataProfilesService.defaultProfile, userDataProfilesService)); + const userDataProfilesService = instantiationService.stub(IUserDataProfilesService, disposables.add(new UserDataProfilesService(environmentService, fileService, uriIdentityService, new NullLogService()))); + instantiationService.stub(IUserDataProfileService, disposables.add(new UserDataProfileService(userDataProfilesService.defaultProfile, userDataProfilesService))); instantiationService.stub(IWorkingCopyBackupService, overrides?.workingCopyBackupService ? overrides?.workingCopyBackupService(instantiationService) : new TestWorkingCopyBackupService()); instantiationService.stub(ITelemetryService, NullTelemetryService); instantiationService.stub(INotificationService, new TestNotificationService()); @@ -305,7 +306,7 @@ export function workbenchInstantiationService( instantiationService.stub(ITextFileService, overrides?.textFileService ? overrides.textFileService(instantiationService) : disposables.add(instantiationService.createInstance(TestTextFileService))); instantiationService.stub(IHostService, instantiationService.createInstance(TestHostService)); instantiationService.stub(ITextModelService, disposables.add(instantiationService.createInstance(TextModelResolverService))); - instantiationService.stub(ILoggerService, new TestLoggerService(TestEnvironmentService.logsHome)); + instantiationService.stub(ILoggerService, disposables.add(new TestLoggerService(TestEnvironmentService.logsHome))); instantiationService.stub(ILogService, new NullLogService()); const editorGroupService = new TestEditorGroupsService([new TestEditorGroupView(0)]); instantiationService.stub(IEditorGroupsService, editorGroupService); @@ -314,10 +315,10 @@ export function workbenchInstantiationService( instantiationService.stub(IEditorService, editorService); instantiationService.stub(IWorkingCopyEditorService, disposables.add(instantiationService.createInstance(WorkingCopyEditorService))); instantiationService.stub(IEditorResolverService, disposables.add(instantiationService.createInstance(EditorResolverService))); - const textEditorService = overrides?.textEditorService ? overrides.textEditorService(instantiationService) : instantiationService.createInstance(TextEditorService); + const textEditorService = overrides?.textEditorService ? overrides.textEditorService(instantiationService) : disposables.add(instantiationService.createInstance(TextEditorService)); instantiationService.stub(ITextEditorService, textEditorService); instantiationService.stub(ICodeEditorService, disposables.add(new CodeEditorService(editorService, themeService, configService))); - instantiationService.stub(IPaneCompositePartService, new TestPaneCompositeService()); + instantiationService.stub(IPaneCompositePartService, disposables.add(new TestPaneCompositeService())); instantiationService.stub(IListService, new TestListService()); const hoverService = instantiationService.stub(IHoverService, instantiationService.createInstance(TestHoverService)); instantiationService.stub(IQuickInputService, disposables.add(new QuickInputService(configService, instantiationService, keybindingService, contextKeyService, themeService, layoutService, hoverService))); From 6885d66040854a29aeee7383ca14efa181c51a74 Mon Sep 17 00:00:00 2001 From: Hans Date: Wed, 23 Aug 2023 20:19:42 +0800 Subject: [PATCH 116/221] adjust tabs and spaces consistent (#184861) --- extensions/html-language-features/.vscode/settings.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/extensions/html-language-features/.vscode/settings.json b/extensions/html-language-features/.vscode/settings.json index 569ac10cf8f..17b02728e8c 100644 --- a/extensions/html-language-features/.vscode/settings.json +++ b/extensions/html-language-features/.vscode/settings.json @@ -1,6 +1,6 @@ { "editor.insertSpaces": false, "prettier.semi": true, - "prettier.singleQuote": true, - "prettier.printWidth": 120, -} \ No newline at end of file + "prettier.singleQuote": true, + "prettier.printWidth": 120 +} From f712b1caba3ecc03f979f09ec8bfc623a0f312ac Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Wed, 23 Aug 2023 05:32:06 -0700 Subject: [PATCH 117/221] Hook up xterm.js trace log level --- .../workbench/contrib/terminal/browser/xterm/xtermTerminal.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/terminal/browser/xterm/xtermTerminal.ts b/src/vs/workbench/contrib/terminal/browser/xterm/xtermTerminal.ts index b5847637730..fcf7a078831 100644 --- a/src/vs/workbench/contrib/terminal/browser/xterm/xtermTerminal.ts +++ b/src/vs/workbench/contrib/terminal/browser/xterm/xtermTerminal.ts @@ -961,7 +961,7 @@ export function getXtermScaledDimensions(font: ITerminalFont, width: number, hei function vscodeToXtermLogLevel(logLevel: LogLevel): XtermLogLevel { switch (logLevel) { - case LogLevel.Trace: + case LogLevel.Trace: return 'trace'; case LogLevel.Debug: return 'debug'; case LogLevel.Info: return 'info'; case LogLevel.Warning: return 'warn'; From d141a1fccee14db6829359b9d8e6d0a153d10f4f Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Wed, 23 Aug 2023 05:47:07 -0700 Subject: [PATCH 118/221] xterm@5.3.0-beta.61 --- package.json | 16 +++++------ remote/package.json | 16 +++++------ remote/web/package.json | 12 ++++---- remote/web/yarn.lock | 48 +++++++++++++++---------------- remote/yarn.lock | 64 ++++++++++++++++++++--------------------- yarn.lock | 64 ++++++++++++++++++++--------------------- 6 files changed, 110 insertions(+), 110 deletions(-) diff --git a/package.json b/package.json index 425451a5559..584247e9fa4 100644 --- a/package.json +++ b/package.json @@ -95,14 +95,14 @@ "vscode-oniguruma": "1.7.0", "vscode-regexpp": "^3.1.0", "vscode-textmate": "9.0.0", - "xterm": "5.3.0-beta.58", - "xterm-addon-canvas": "0.5.0-beta.19", - "xterm-addon-image": "0.6.0-beta.11", - "xterm-addon-search": "0.13.0-beta.17", - "xterm-addon-serialize": "0.11.0-beta.17", - "xterm-addon-unicode11": "0.6.0-beta.9", - "xterm-addon-webgl": "0.16.0-beta.27", - "xterm-headless": "5.3.0-beta.58", + "xterm": "5.3.0-beta.61", + "xterm-addon-canvas": "0.5.0-beta.22", + "xterm-addon-image": "0.6.0-beta.14", + "xterm-addon-search": "0.13.0-beta.20", + "xterm-addon-serialize": "0.11.0-beta.20", + "xterm-addon-unicode11": "0.6.0-beta.12", + "xterm-addon-webgl": "0.16.0-beta.30", + "xterm-headless": "5.3.0-beta.61", "yauzl": "^2.9.2", "yazl": "^2.4.3" }, diff --git a/remote/package.json b/remote/package.json index 6d6a0152a55..8fe0e55c1de 100644 --- a/remote/package.json +++ b/remote/package.json @@ -27,14 +27,14 @@ "vscode-oniguruma": "1.7.0", "vscode-regexpp": "^3.1.0", "vscode-textmate": "9.0.0", - "xterm": "5.3.0-beta.58", - "xterm-addon-canvas": "0.5.0-beta.19", - "xterm-addon-image": "0.6.0-beta.11", - "xterm-addon-search": "0.13.0-beta.17", - "xterm-addon-serialize": "0.11.0-beta.17", - "xterm-addon-unicode11": "0.6.0-beta.9", - "xterm-addon-webgl": "0.16.0-beta.27", - "xterm-headless": "5.3.0-beta.58", + "xterm": "5.3.0-beta.61", + "xterm-addon-canvas": "0.5.0-beta.22", + "xterm-addon-image": "0.6.0-beta.14", + "xterm-addon-search": "0.13.0-beta.20", + "xterm-addon-serialize": "0.11.0-beta.20", + "xterm-addon-unicode11": "0.6.0-beta.12", + "xterm-addon-webgl": "0.16.0-beta.30", + "xterm-headless": "5.3.0-beta.61", "yauzl": "^2.9.2", "yazl": "^2.4.3" } diff --git a/remote/web/package.json b/remote/web/package.json index 05686230a43..6075a563e34 100644 --- a/remote/web/package.json +++ b/remote/web/package.json @@ -11,11 +11,11 @@ "tas-client-umd": "0.1.8", "vscode-oniguruma": "1.7.0", "vscode-textmate": "9.0.0", - "xterm": "5.3.0-beta.58", - "xterm-addon-canvas": "0.5.0-beta.19", - "xterm-addon-image": "0.6.0-beta.11", - "xterm-addon-search": "0.13.0-beta.17", - "xterm-addon-unicode11": "0.6.0-beta.9", - "xterm-addon-webgl": "0.16.0-beta.27" + "xterm": "5.3.0-beta.61", + "xterm-addon-canvas": "0.5.0-beta.22", + "xterm-addon-image": "0.6.0-beta.14", + "xterm-addon-search": "0.13.0-beta.20", + "xterm-addon-unicode11": "0.6.0-beta.12", + "xterm-addon-webgl": "0.16.0-beta.30" } } diff --git a/remote/web/yarn.lock b/remote/web/yarn.lock index dc817e45bf1..b56fac51a45 100644 --- a/remote/web/yarn.lock +++ b/remote/web/yarn.lock @@ -68,32 +68,32 @@ vscode-textmate@9.0.0: resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-9.0.0.tgz#313c6c8792b0507aef35aeb81b6b370b37c44d6c" integrity sha512-Cl65diFGxz7gpwbav10HqiY/eVYTO1sjQpmRmV991Bj7wAoOAjGQ97PpQcXorDE2Uc4hnGWLY17xme+5t6MlSg== -xterm-addon-canvas@0.5.0-beta.19: - version "0.5.0-beta.19" - resolved "https://registry.yarnpkg.com/xterm-addon-canvas/-/xterm-addon-canvas-0.5.0-beta.19.tgz#a2b67554191fae29c901c4a4b398fc28dc345afe" - integrity sha512-eF6b7SBZslmwqCLiWTGnjna4bdjd28cQ+ivZH8SVjE5xP3JGAHGWs/fZm5E3eR6pcHEOkX++/FxByuvhOVXIXQ== +xterm-addon-canvas@0.5.0-beta.22: + version "0.5.0-beta.22" + resolved "https://registry.yarnpkg.com/xterm-addon-canvas/-/xterm-addon-canvas-0.5.0-beta.22.tgz#513f0c2b7cf96073f47627b27e8965c1b1a22431" + integrity sha512-9F6ZI0DMRgffVfHkLkDwl5n8VscvCaV10tWI3skXOX7Y7Aws6OEeglkOPoU3IllofCU792kHKM4pPoToUxTltg== -xterm-addon-image@0.6.0-beta.11: - version "0.6.0-beta.11" - resolved "https://registry.yarnpkg.com/xterm-addon-image/-/xterm-addon-image-0.6.0-beta.11.tgz#17dffc5f38480a4fac231649ef6e313a8f46d614" - integrity sha512-KPsqJo8sSAawO4ze7xvjtS5evbPtlscy16NiSAteh/1AgOffmTnVhJTs3W84dnks2b13FaMEI/WOiCDIJjDV3A== +xterm-addon-image@0.6.0-beta.14: + version "0.6.0-beta.14" + resolved "https://registry.yarnpkg.com/xterm-addon-image/-/xterm-addon-image-0.6.0-beta.14.tgz#75fc3f824123183a4bbb5306e22f8b2c6966b0a6" + integrity sha512-D5Gh5JTKhHaPt1KwQNf6diF37KA4eToJw3XId1wy62tWmSqfq+QflhOGTfd+SnSQYCktU05ETzM+0tncIU62pQ== -xterm-addon-search@0.13.0-beta.17: - version "0.13.0-beta.17" - resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.13.0-beta.17.tgz#5379cf3085370c55241d99e95b008c0cbf4e6e53" - integrity sha512-0OKwV9isk4OXHLlhRE8Ohqnmpcd0ExWKtorjeaFxqm4f6xc30qZcJTs0hSMzVZ83foedPJcd6hH0hW2pnxOz3Q== +xterm-addon-search@0.13.0-beta.20: + version "0.13.0-beta.20" + resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.13.0-beta.20.tgz#8ddd0513e2a70fcefa325722100d2e1bfaf3b9cb" + integrity sha512-wrx6187cJ1UenGL6ZeYv3jFvRPhhENTfbC+Hv1Fnww8LmsKhcj+0+Pm6yInNjX/9hNVsNzdqKyqNeEMoykyoyA== -xterm-addon-unicode11@0.6.0-beta.9: - version "0.6.0-beta.9" - resolved "https://registry.yarnpkg.com/xterm-addon-unicode11/-/xterm-addon-unicode11-0.6.0-beta.9.tgz#1f476f77cf8c8e4e7ca1a1421b85ac45405db679" - integrity sha512-DH9OIH0EakIdCnzZcIH7NLgUqXwa8WT9fqmi+2CWzt4NN1AH5kSE/3Vk+/uurE5upxDloKw6dtLH9XHpfULV6g== +xterm-addon-unicode11@0.6.0-beta.12: + version "0.6.0-beta.12" + resolved "https://registry.yarnpkg.com/xterm-addon-unicode11/-/xterm-addon-unicode11-0.6.0-beta.12.tgz#ac6df9d635325dc692e4c602e74a2fc27a09405c" + integrity sha512-9wWWf/5nFafYgq0pn9EgAWnXaXGleVxfjNOqavpLRYFv0nw42QbaYyGvnGcxyYHM5Aqx/8rYE/DDVWZBqQZdYA== -xterm-addon-webgl@0.16.0-beta.27: - version "0.16.0-beta.27" - resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.16.0-beta.27.tgz#f4133a40044f0b6448ea87152abf6c9009729100" - integrity sha512-YiwCvTvgfcNGtQdpzcgxKINE6mG63cPfDxfoxCAbodNGYF66k9VzhIXNdCQtVtu+s6+pEc9YequENe78SSZloA== +xterm-addon-webgl@0.16.0-beta.30: + version "0.16.0-beta.30" + resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.16.0-beta.30.tgz#820d5c65f868b14ec4177bfb8a294931a53616bf" + integrity sha512-39qPHPFmNENxcHf8/CzGHS6wzKMMegoRkHB1+scqtBhSxFaD8tX5Ye33HZIEdQ9nXe9xtr4FWVp77T+n9hdrew== -xterm@5.3.0-beta.58: - version "5.3.0-beta.58" - resolved "https://registry.yarnpkg.com/xterm/-/xterm-5.3.0-beta.58.tgz#4bae06639c90952b270e4714938c151ce339b5f0" - integrity sha512-EIOgp+7aqCToI0XjDqORXAe2lJS/XSZXWPzCpyTDmF+DJ56gyw+913gdPoIEWOw3mRylrJtEyIpFcdW7CDA6rQ== +xterm@5.3.0-beta.61: + version "5.3.0-beta.61" + resolved "https://registry.yarnpkg.com/xterm/-/xterm-5.3.0-beta.61.tgz#a6c27d90a5314da51d80deeb32f3bd77f1e1c8f6" + integrity sha512-rJHpCc48GSpHnu0SSERynQ80D5ikvFVsqhv6JdmeONTrnAFRr134OglJRIpbi2YK8UPbV6F6Dfqm/AQh+9GZzA== diff --git a/remote/yarn.lock b/remote/yarn.lock index 68c99905917..4716df355d5 100644 --- a/remote/yarn.lock +++ b/remote/yarn.lock @@ -877,45 +877,45 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= -xterm-addon-canvas@0.5.0-beta.19: - version "0.5.0-beta.19" - resolved "https://registry.yarnpkg.com/xterm-addon-canvas/-/xterm-addon-canvas-0.5.0-beta.19.tgz#a2b67554191fae29c901c4a4b398fc28dc345afe" - integrity sha512-eF6b7SBZslmwqCLiWTGnjna4bdjd28cQ+ivZH8SVjE5xP3JGAHGWs/fZm5E3eR6pcHEOkX++/FxByuvhOVXIXQ== +xterm-addon-canvas@0.5.0-beta.22: + version "0.5.0-beta.22" + resolved "https://registry.yarnpkg.com/xterm-addon-canvas/-/xterm-addon-canvas-0.5.0-beta.22.tgz#513f0c2b7cf96073f47627b27e8965c1b1a22431" + integrity sha512-9F6ZI0DMRgffVfHkLkDwl5n8VscvCaV10tWI3skXOX7Y7Aws6OEeglkOPoU3IllofCU792kHKM4pPoToUxTltg== -xterm-addon-image@0.6.0-beta.11: - version "0.6.0-beta.11" - resolved "https://registry.yarnpkg.com/xterm-addon-image/-/xterm-addon-image-0.6.0-beta.11.tgz#17dffc5f38480a4fac231649ef6e313a8f46d614" - integrity sha512-KPsqJo8sSAawO4ze7xvjtS5evbPtlscy16NiSAteh/1AgOffmTnVhJTs3W84dnks2b13FaMEI/WOiCDIJjDV3A== +xterm-addon-image@0.6.0-beta.14: + version "0.6.0-beta.14" + resolved "https://registry.yarnpkg.com/xterm-addon-image/-/xterm-addon-image-0.6.0-beta.14.tgz#75fc3f824123183a4bbb5306e22f8b2c6966b0a6" + integrity sha512-D5Gh5JTKhHaPt1KwQNf6diF37KA4eToJw3XId1wy62tWmSqfq+QflhOGTfd+SnSQYCktU05ETzM+0tncIU62pQ== -xterm-addon-search@0.13.0-beta.17: - version "0.13.0-beta.17" - resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.13.0-beta.17.tgz#5379cf3085370c55241d99e95b008c0cbf4e6e53" - integrity sha512-0OKwV9isk4OXHLlhRE8Ohqnmpcd0ExWKtorjeaFxqm4f6xc30qZcJTs0hSMzVZ83foedPJcd6hH0hW2pnxOz3Q== +xterm-addon-search@0.13.0-beta.20: + version "0.13.0-beta.20" + resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.13.0-beta.20.tgz#8ddd0513e2a70fcefa325722100d2e1bfaf3b9cb" + integrity sha512-wrx6187cJ1UenGL6ZeYv3jFvRPhhENTfbC+Hv1Fnww8LmsKhcj+0+Pm6yInNjX/9hNVsNzdqKyqNeEMoykyoyA== -xterm-addon-serialize@0.11.0-beta.17: - version "0.11.0-beta.17" - resolved "https://registry.yarnpkg.com/xterm-addon-serialize/-/xterm-addon-serialize-0.11.0-beta.17.tgz#170738ab615e2974c593d41531d41c02b8af1da7" - integrity sha512-zNsUQfIbRD8fL0gHGJJ14DXL22Kduv6pR+QnISReoQqhEEsWANPKpOduJLce7B4y+BJuiOGkT7R7qbMKbj9Ecw== +xterm-addon-serialize@0.11.0-beta.20: + version "0.11.0-beta.20" + resolved "https://registry.yarnpkg.com/xterm-addon-serialize/-/xterm-addon-serialize-0.11.0-beta.20.tgz#e879b34d214761403f1081833f9221c6903bf0c3" + integrity sha512-OXnC1SATaz7kEFjFWhyv9MJaXi8yHdPjazpGLNi11h33CRTKtCQiqqPBHU87dztnXmpEX6Jw0/jr3zlyXuAmnw== -xterm-addon-unicode11@0.6.0-beta.9: - version "0.6.0-beta.9" - resolved "https://registry.yarnpkg.com/xterm-addon-unicode11/-/xterm-addon-unicode11-0.6.0-beta.9.tgz#1f476f77cf8c8e4e7ca1a1421b85ac45405db679" - integrity sha512-DH9OIH0EakIdCnzZcIH7NLgUqXwa8WT9fqmi+2CWzt4NN1AH5kSE/3Vk+/uurE5upxDloKw6dtLH9XHpfULV6g== +xterm-addon-unicode11@0.6.0-beta.12: + version "0.6.0-beta.12" + resolved "https://registry.yarnpkg.com/xterm-addon-unicode11/-/xterm-addon-unicode11-0.6.0-beta.12.tgz#ac6df9d635325dc692e4c602e74a2fc27a09405c" + integrity sha512-9wWWf/5nFafYgq0pn9EgAWnXaXGleVxfjNOqavpLRYFv0nw42QbaYyGvnGcxyYHM5Aqx/8rYE/DDVWZBqQZdYA== -xterm-addon-webgl@0.16.0-beta.27: - version "0.16.0-beta.27" - resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.16.0-beta.27.tgz#f4133a40044f0b6448ea87152abf6c9009729100" - integrity sha512-YiwCvTvgfcNGtQdpzcgxKINE6mG63cPfDxfoxCAbodNGYF66k9VzhIXNdCQtVtu+s6+pEc9YequENe78SSZloA== +xterm-addon-webgl@0.16.0-beta.30: + version "0.16.0-beta.30" + resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.16.0-beta.30.tgz#820d5c65f868b14ec4177bfb8a294931a53616bf" + integrity sha512-39qPHPFmNENxcHf8/CzGHS6wzKMMegoRkHB1+scqtBhSxFaD8tX5Ye33HZIEdQ9nXe9xtr4FWVp77T+n9hdrew== -xterm-headless@5.3.0-beta.58: - version "5.3.0-beta.58" - resolved "https://registry.yarnpkg.com/xterm-headless/-/xterm-headless-5.3.0-beta.58.tgz#e6a3dbfafdb28435130ce3925ac3194c0ee2c281" - integrity sha512-ekzr3LX8p26qHDyVRs3lys08veHFv9wGOKaHd49kMgktICHsikJ48HNJq5Twp3ZnXyqlIP9CV34BZJ1SBfWmtQ== +xterm-headless@5.3.0-beta.61: + version "5.3.0-beta.61" + resolved "https://registry.yarnpkg.com/xterm-headless/-/xterm-headless-5.3.0-beta.61.tgz#28654550cb572709b99ea3eb8672d4568ae141c9" + integrity sha512-yfkbPLUtKjE4K7DsZ204A1BuOKpu6Usqi6rIYWT4XRMi+LjnkTbBjGr2BSjyJ3Gmtm+cSgBD0SvRN+V3xNxbxA== -xterm@5.3.0-beta.58: - version "5.3.0-beta.58" - resolved "https://registry.yarnpkg.com/xterm/-/xterm-5.3.0-beta.58.tgz#4bae06639c90952b270e4714938c151ce339b5f0" - integrity sha512-EIOgp+7aqCToI0XjDqORXAe2lJS/XSZXWPzCpyTDmF+DJ56gyw+913gdPoIEWOw3mRylrJtEyIpFcdW7CDA6rQ== +xterm@5.3.0-beta.61: + version "5.3.0-beta.61" + resolved "https://registry.yarnpkg.com/xterm/-/xterm-5.3.0-beta.61.tgz#a6c27d90a5314da51d80deeb32f3bd77f1e1c8f6" + integrity sha512-rJHpCc48GSpHnu0SSERynQ80D5ikvFVsqhv6JdmeONTrnAFRr134OglJRIpbi2YK8UPbV6F6Dfqm/AQh+9GZzA== yallist@^4.0.0: version "4.0.0" diff --git a/yarn.lock b/yarn.lock index 96c77bcd45a..5595e14de37 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10759,45 +10759,45 @@ xtend@~2.1.1: dependencies: object-keys "~0.4.0" -xterm-addon-canvas@0.5.0-beta.19: - version "0.5.0-beta.19" - resolved "https://registry.yarnpkg.com/xterm-addon-canvas/-/xterm-addon-canvas-0.5.0-beta.19.tgz#a2b67554191fae29c901c4a4b398fc28dc345afe" - integrity sha512-eF6b7SBZslmwqCLiWTGnjna4bdjd28cQ+ivZH8SVjE5xP3JGAHGWs/fZm5E3eR6pcHEOkX++/FxByuvhOVXIXQ== +xterm-addon-canvas@0.5.0-beta.22: + version "0.5.0-beta.22" + resolved "https://registry.yarnpkg.com/xterm-addon-canvas/-/xterm-addon-canvas-0.5.0-beta.22.tgz#513f0c2b7cf96073f47627b27e8965c1b1a22431" + integrity sha512-9F6ZI0DMRgffVfHkLkDwl5n8VscvCaV10tWI3skXOX7Y7Aws6OEeglkOPoU3IllofCU792kHKM4pPoToUxTltg== -xterm-addon-image@0.6.0-beta.11: - version "0.6.0-beta.11" - resolved "https://registry.yarnpkg.com/xterm-addon-image/-/xterm-addon-image-0.6.0-beta.11.tgz#17dffc5f38480a4fac231649ef6e313a8f46d614" - integrity sha512-KPsqJo8sSAawO4ze7xvjtS5evbPtlscy16NiSAteh/1AgOffmTnVhJTs3W84dnks2b13FaMEI/WOiCDIJjDV3A== +xterm-addon-image@0.6.0-beta.14: + version "0.6.0-beta.14" + resolved "https://registry.yarnpkg.com/xterm-addon-image/-/xterm-addon-image-0.6.0-beta.14.tgz#75fc3f824123183a4bbb5306e22f8b2c6966b0a6" + integrity sha512-D5Gh5JTKhHaPt1KwQNf6diF37KA4eToJw3XId1wy62tWmSqfq+QflhOGTfd+SnSQYCktU05ETzM+0tncIU62pQ== -xterm-addon-search@0.13.0-beta.17: - version "0.13.0-beta.17" - resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.13.0-beta.17.tgz#5379cf3085370c55241d99e95b008c0cbf4e6e53" - integrity sha512-0OKwV9isk4OXHLlhRE8Ohqnmpcd0ExWKtorjeaFxqm4f6xc30qZcJTs0hSMzVZ83foedPJcd6hH0hW2pnxOz3Q== +xterm-addon-search@0.13.0-beta.20: + version "0.13.0-beta.20" + resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.13.0-beta.20.tgz#8ddd0513e2a70fcefa325722100d2e1bfaf3b9cb" + integrity sha512-wrx6187cJ1UenGL6ZeYv3jFvRPhhENTfbC+Hv1Fnww8LmsKhcj+0+Pm6yInNjX/9hNVsNzdqKyqNeEMoykyoyA== -xterm-addon-serialize@0.11.0-beta.17: - version "0.11.0-beta.17" - resolved "https://registry.yarnpkg.com/xterm-addon-serialize/-/xterm-addon-serialize-0.11.0-beta.17.tgz#170738ab615e2974c593d41531d41c02b8af1da7" - integrity sha512-zNsUQfIbRD8fL0gHGJJ14DXL22Kduv6pR+QnISReoQqhEEsWANPKpOduJLce7B4y+BJuiOGkT7R7qbMKbj9Ecw== +xterm-addon-serialize@0.11.0-beta.20: + version "0.11.0-beta.20" + resolved "https://registry.yarnpkg.com/xterm-addon-serialize/-/xterm-addon-serialize-0.11.0-beta.20.tgz#e879b34d214761403f1081833f9221c6903bf0c3" + integrity sha512-OXnC1SATaz7kEFjFWhyv9MJaXi8yHdPjazpGLNi11h33CRTKtCQiqqPBHU87dztnXmpEX6Jw0/jr3zlyXuAmnw== -xterm-addon-unicode11@0.6.0-beta.9: - version "0.6.0-beta.9" - resolved "https://registry.yarnpkg.com/xterm-addon-unicode11/-/xterm-addon-unicode11-0.6.0-beta.9.tgz#1f476f77cf8c8e4e7ca1a1421b85ac45405db679" - integrity sha512-DH9OIH0EakIdCnzZcIH7NLgUqXwa8WT9fqmi+2CWzt4NN1AH5kSE/3Vk+/uurE5upxDloKw6dtLH9XHpfULV6g== +xterm-addon-unicode11@0.6.0-beta.12: + version "0.6.0-beta.12" + resolved "https://registry.yarnpkg.com/xterm-addon-unicode11/-/xterm-addon-unicode11-0.6.0-beta.12.tgz#ac6df9d635325dc692e4c602e74a2fc27a09405c" + integrity sha512-9wWWf/5nFafYgq0pn9EgAWnXaXGleVxfjNOqavpLRYFv0nw42QbaYyGvnGcxyYHM5Aqx/8rYE/DDVWZBqQZdYA== -xterm-addon-webgl@0.16.0-beta.27: - version "0.16.0-beta.27" - resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.16.0-beta.27.tgz#f4133a40044f0b6448ea87152abf6c9009729100" - integrity sha512-YiwCvTvgfcNGtQdpzcgxKINE6mG63cPfDxfoxCAbodNGYF66k9VzhIXNdCQtVtu+s6+pEc9YequENe78SSZloA== +xterm-addon-webgl@0.16.0-beta.30: + version "0.16.0-beta.30" + resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.16.0-beta.30.tgz#820d5c65f868b14ec4177bfb8a294931a53616bf" + integrity sha512-39qPHPFmNENxcHf8/CzGHS6wzKMMegoRkHB1+scqtBhSxFaD8tX5Ye33HZIEdQ9nXe9xtr4FWVp77T+n9hdrew== -xterm-headless@5.3.0-beta.58: - version "5.3.0-beta.58" - resolved "https://registry.yarnpkg.com/xterm-headless/-/xterm-headless-5.3.0-beta.58.tgz#e6a3dbfafdb28435130ce3925ac3194c0ee2c281" - integrity sha512-ekzr3LX8p26qHDyVRs3lys08veHFv9wGOKaHd49kMgktICHsikJ48HNJq5Twp3ZnXyqlIP9CV34BZJ1SBfWmtQ== +xterm-headless@5.3.0-beta.61: + version "5.3.0-beta.61" + resolved "https://registry.yarnpkg.com/xterm-headless/-/xterm-headless-5.3.0-beta.61.tgz#28654550cb572709b99ea3eb8672d4568ae141c9" + integrity sha512-yfkbPLUtKjE4K7DsZ204A1BuOKpu6Usqi6rIYWT4XRMi+LjnkTbBjGr2BSjyJ3Gmtm+cSgBD0SvRN+V3xNxbxA== -xterm@5.3.0-beta.58: - version "5.3.0-beta.58" - resolved "https://registry.yarnpkg.com/xterm/-/xterm-5.3.0-beta.58.tgz#4bae06639c90952b270e4714938c151ce339b5f0" - integrity sha512-EIOgp+7aqCToI0XjDqORXAe2lJS/XSZXWPzCpyTDmF+DJ56gyw+913gdPoIEWOw3mRylrJtEyIpFcdW7CDA6rQ== +xterm@5.3.0-beta.61: + version "5.3.0-beta.61" + resolved "https://registry.yarnpkg.com/xterm/-/xterm-5.3.0-beta.61.tgz#a6c27d90a5314da51d80deeb32f3bd77f1e1c8f6" + integrity sha512-rJHpCc48GSpHnu0SSERynQ80D5ikvFVsqhv6JdmeONTrnAFRr134OglJRIpbi2YK8UPbV6F6Dfqm/AQh+9GZzA== y18n@^3.2.1: version "3.2.2" From 8e524deece95d3aa772af5ce974e8a3a4aca422f Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Wed, 23 Aug 2023 14:57:53 +0200 Subject: [PATCH 119/221] not rendering when model is too large for tokenization --- .../contrib/stickyScroll/browser/stickyScrollController.ts | 5 ++--- .../contrib/codeEditor/browser/largeFileOptimizations.ts | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/vs/editor/contrib/stickyScroll/browser/stickyScrollController.ts b/src/vs/editor/contrib/stickyScroll/browser/stickyScrollController.ts index 37647eccdf6..5764622526d 100644 --- a/src/vs/editor/contrib/stickyScroll/browser/stickyScrollController.ts +++ b/src/vs/editor/contrib/stickyScroll/browser/stickyScrollController.ts @@ -370,7 +370,6 @@ export class StickyScrollController extends Disposable implements IEditorContrib private _readConfiguration() { const options = this._editor.getOption(EditorOption.stickyScroll); - if (options.enabled === false) { this._editor.removeOverlayWidget(this._stickyScrollWidget); this._sessionStore.clear(); @@ -429,10 +428,10 @@ export class StickyScrollController extends Disposable implements IEditorContrib } private _renderStickyScroll() { - if (!(this._editor.hasModel())) { + const model = this._editor.getModel(); + if (!model || model.isTooLargeForTokenization()) { return; } - const model = this._editor.getModel(); const stickyLineVersion = this._stickyLineCandidateProvider.getVersionId(); if (stickyLineVersion === undefined || stickyLineVersion === model.getVersionId()) { this._widgetState = this.findScrollWidgetState(); diff --git a/src/vs/workbench/contrib/codeEditor/browser/largeFileOptimizations.ts b/src/vs/workbench/contrib/codeEditor/browser/largeFileOptimizations.ts index 80e766a2a4f..52ac3a4afb1 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/largeFileOptimizations.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/largeFileOptimizations.ts @@ -44,7 +44,7 @@ export class LargeFileOptimizationsWarner extends Disposable implements IEditorC 'Variable 0 will be a file name.' ] }, - "{0}: tokenization, wrapping and folding have been turned off for this large file in order to reduce memory usage and avoid freezing or crashing.", + "{0}: tokenization, wrapping, folding and sticky scroll have been turned off for this large file in order to reduce memory usage and avoid freezing or crashing.", path.basename(model.uri.path) ); From 1461c7d38225e5450d3d059b7872593a99d44df3 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Wed, 23 Aug 2023 07:54:24 -0700 Subject: [PATCH 120/221] Finalize EnvironmentVariableMutatorOptions API Fixes #179476 --- extensions/vscode-api-tests/package.json | 3 +- .../api/common/extHostTerminalService.ts | 9 --- .../common/extensionsApiProposals.ts | 1 - src/vscode-dts/vscode.d.ts | 33 ++++++++++- .../vscode.proposed.envCollectionOptions.d.ts | 55 ------------------- 5 files changed, 31 insertions(+), 70 deletions(-) delete mode 100644 src/vscode-dts/vscode.proposed.envCollectionOptions.d.ts diff --git a/extensions/vscode-api-tests/package.json b/extensions/vscode-api-tests/package.json index 9d50e393547..ac6fb719a90 100644 --- a/extensions/vscode-api-tests/package.json +++ b/extensions/vscode-api-tests/package.json @@ -52,8 +52,7 @@ "telemetry", "windowActivity", "interactiveUserActions", - "envCollectionWorkspace", - "envCollectionOptions" + "envCollectionWorkspace" ], "private": true, "activationEvents": [], diff --git a/src/vs/workbench/api/common/extHostTerminalService.ts b/src/vs/workbench/api/common/extHostTerminalService.ts index c7d8b2a83d0..c901a5cae3d 100644 --- a/src/vs/workbench/api/common/extHostTerminalService.ts +++ b/src/vs/workbench/api/common/extHostTerminalService.ts @@ -944,23 +944,14 @@ class UnifiedEnvironmentVariableCollection { } replace(variable: string, value: string, options: vscode.EnvironmentVariableMutatorOptions | undefined, scope: vscode.EnvironmentVariableScope | undefined): void { - if (this._extension && options) { - checkProposedApiEnabled(this._extension, 'envCollectionOptions'); - } this._setIfDiffers(variable, { value, type: EnvironmentVariableMutatorType.Replace, options: options ?? { applyAtProcessCreation: true }, scope }); } append(variable: string, value: string, options: vscode.EnvironmentVariableMutatorOptions | undefined, scope: vscode.EnvironmentVariableScope | undefined): void { - if (this._extension && options) { - checkProposedApiEnabled(this._extension, 'envCollectionOptions'); - } this._setIfDiffers(variable, { value, type: EnvironmentVariableMutatorType.Append, options: options ?? { applyAtProcessCreation: true }, scope }); } prepend(variable: string, value: string, options: vscode.EnvironmentVariableMutatorOptions | undefined, scope: vscode.EnvironmentVariableScope | undefined): void { - if (this._extension && options) { - checkProposedApiEnabled(this._extension, 'envCollectionOptions'); - } this._setIfDiffers(variable, { value, type: EnvironmentVariableMutatorType.Prepend, options: options ?? { applyAtProcessCreation: true }, scope }); } diff --git a/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts b/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts index 03d80474dad..be411915ec1 100644 --- a/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts +++ b/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts @@ -40,7 +40,6 @@ export const allApiProposals = Object.freeze({ dropMetadata: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.dropMetadata.d.ts', editSessionIdentityProvider: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.editSessionIdentityProvider.d.ts', editorInsets: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.editorInsets.d.ts', - envCollectionOptions: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.envCollectionOptions.d.ts', envCollectionWorkspace: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.envCollectionWorkspace.d.ts', envShellEvent: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.envShellEvent.d.ts', extensionRuntime: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.extensionRuntime.d.ts', diff --git a/src/vscode-dts/vscode.d.ts b/src/vscode-dts/vscode.d.ts index db7d29f3b1b..6c962d2e0fd 100644 --- a/src/vscode-dts/vscode.d.ts +++ b/src/vscode-dts/vscode.d.ts @@ -11334,6 +11334,22 @@ declare module 'vscode' { Prepend = 3 } + /** + * Options applied to the mutator. + */ + export interface EnvironmentVariableMutatorOptions { + /** + * Apply to the environment just before the process is created. + */ + applyAtProcessCreation?: boolean; + + /** + * Apply to the environment in the shell integration script. Note that this _will not_ apply + * the mutator if shell integration is disabled or not working for some reason. + */ + applyAtShellIntegration?: boolean; + } + /** * A type of mutation and its value to be applied to an environment variable. */ @@ -11347,6 +11363,11 @@ declare module 'vscode' { * The value to use for the variable. */ readonly value: string; + + /** + * Options applied to the mutator. + */ + readonly options: EnvironmentVariableMutatorOptions; } /** @@ -11376,8 +11397,10 @@ declare module 'vscode' { * * @param variable The variable to replace. * @param value The value to replace the variable with. + * @param options Options applied to the mutator, when no options are provided this will + * default to `{ applyAtProcessCreation: true }`. */ - replace(variable: string, value: string): void; + replace(variable: string, value: string, options?: EnvironmentVariableMutatorOptions): void; /** * Append a value to an environment variable. @@ -11387,8 +11410,10 @@ declare module 'vscode' { * * @param variable The variable to append to. * @param value The value to append to the variable. + * @param options Options applied to the mutator, when no options are provided this will + * default to `{ applyAtProcessCreation: true }`. */ - append(variable: string, value: string): void; + append(variable: string, value: string, options?: EnvironmentVariableMutatorOptions): void; /** * Prepend a value to an environment variable. @@ -11398,8 +11423,10 @@ declare module 'vscode' { * * @param variable The variable to prepend. * @param value The value to prepend to the variable. + * @param options Options applied to the mutator, when no options are provided this will + * default to `{ applyAtProcessCreation: true }`. */ - prepend(variable: string, value: string): void; + prepend(variable: string, value: string, options?: EnvironmentVariableMutatorOptions): void; /** * Gets the mutator that this collection applies to a variable, if any. diff --git a/src/vscode-dts/vscode.proposed.envCollectionOptions.d.ts b/src/vscode-dts/vscode.proposed.envCollectionOptions.d.ts deleted file mode 100644 index 1de5bed146e..00000000000 --- a/src/vscode-dts/vscode.proposed.envCollectionOptions.d.ts +++ /dev/null @@ -1,55 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -declare module 'vscode' { - - // https://github.com/microsoft/vscode/issues/179476 - - /** - * Options applied to the mutator. - */ - export interface EnvironmentVariableMutatorOptions { - /** - * Apply to the environment just before the process is created. - */ - applyAtProcessCreation?: boolean; - - /** - * Apply to the environment in the shell integration script. Note that this _will not_ apply - * the mutator if shell integration is disabled or not working for some reason. - */ - applyAtShellIntegration?: boolean; - } - - /** - * A type of mutation and its value to be applied to an environment variable. - */ - export interface EnvironmentVariableMutator { - /** - * Options applied to the mutator. - */ - readonly options: EnvironmentVariableMutatorOptions; - } - - export interface EnvironmentVariableCollection extends Iterable<[variable: string, mutator: EnvironmentVariableMutator]> { - /** - * @param options Options applied to the mutator, when not options are provided this will - * default to `{ applyAtProcessCreation: true }` - */ - replace(variable: string, value: string, options?: EnvironmentVariableMutatorOptions): void; - - /** - * @param options Options applied to the mutator, when not options are provided this will - * default to `{ applyAtProcessCreation: true }` - */ - append(variable: string, value: string, options?: EnvironmentVariableMutatorOptions): void; - - /** - * @param options Options applied to the mutator, when not options are provided this will - * default to `{ applyAtProcessCreation: true }` - */ - prepend(variable: string, value: string, options?: EnvironmentVariableMutatorOptions): void; - } -} From 2d3235f7474a807220f5a3c48219f92ab331c9e6 Mon Sep 17 00:00:00 2001 From: Hans Date: Wed, 23 Aug 2023 23:17:37 +0800 Subject: [PATCH 121/221] =?UTF-8?q?immediately=20search=20after=20enter=20?= =?UTF-8?q?pressed=20in=20files=20to=20include/exclude=20te=E2=80=A6=20(#1?= =?UTF-8?q?90473)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit immediately search after enter pressed in files to include/exclude text fields. --- src/vs/workbench/contrib/search/browser/searchView.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/search/browser/searchView.ts b/src/vs/workbench/contrib/search/browser/searchView.ts index cf7506c874c..6df2f295095 100644 --- a/src/vs/workbench/contrib/search/browser/searchView.ts +++ b/src/vs/workbench/contrib/search/browser/searchView.ts @@ -1454,9 +1454,11 @@ export class SearchView extends ViewPane { if (options.triggeredOnType && !this.searchConfig.searchOnType) { return; } if (!this.pauseSearching) { + + const delay = options.triggeredOnType ? options.delay : 0; this.triggerQueryDelayer.trigger(() => { this._onQueryChanged(options.preserveFocus, options.triggeredOnType); - }, options.delay); + }, delay); } } From 2e95e033cf014820e60f382c759be2b25a231114 Mon Sep 17 00:00:00 2001 From: Andrea Mah <31675041+andreamah@users.noreply.github.com> Date: Wed, 23 Aug 2023 08:20:33 -0700 Subject: [PATCH 122/221] support for fastAndSlow picks in quick search (#191002) --- .../browser/notebookSearchContributions.ts | 2 +- .../search/browser/notebookSearchService.ts | 83 +++++++----- .../quickTextSearch/textSearchQuickAccess.ts | 72 ++++++---- .../contrib/search/browser/replaceService.ts | 4 +- .../search/browser/search.contribution.ts | 4 +- .../contrib/search/browser/searchModel.ts | 114 +++++++++++----- .../contrib/search/browser/searchView.ts | 10 +- .../{browser => common}/notebookSearch.ts | 6 +- .../search/test/browser/searchModel.test.ts | 123 +++++++++++++----- .../searchEditor/browser/searchEditor.ts | 4 +- .../services/search/common/search.ts | 4 +- .../services/search/common/searchService.ts | 80 ++++++++---- 12 files changed, 341 insertions(+), 165 deletions(-) rename src/vs/workbench/contrib/search/{browser => common}/notebookSearch.ts (75%) diff --git a/src/vs/workbench/contrib/search/browser/notebookSearchContributions.ts b/src/vs/workbench/contrib/search/browser/notebookSearchContributions.ts index 03b44bf0026..57d73a21c3f 100644 --- a/src/vs/workbench/contrib/search/browser/notebookSearchContributions.ts +++ b/src/vs/workbench/contrib/search/browser/notebookSearchContributions.ts @@ -7,7 +7,7 @@ import { ReplacePreviewContentProvider } from 'vs/workbench/contrib/search/brows import { Registry } from 'vs/platform/registry/common/platform'; import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions'; import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle'; -import { INotebookSearchService } from 'vs/workbench/contrib/search/browser/notebookSearch'; +import { INotebookSearchService } from 'vs/workbench/contrib/search/common/notebookSearch'; import { NotebookSearchService } from 'vs/workbench/contrib/search/browser/notebookSearchService'; export function registerContributions(): void { diff --git a/src/vs/workbench/contrib/search/browser/notebookSearchService.ts b/src/vs/workbench/contrib/search/browser/notebookSearchService.ts index adee7532d41..19b45f30903 100644 --- a/src/vs/workbench/contrib/search/browser/notebookSearchService.ts +++ b/src/vs/workbench/contrib/search/browser/notebookSearchService.ts @@ -18,10 +18,10 @@ import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/mode import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel'; import { INotebookExclusiveDocumentFilter, NotebookData } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { INotebookSerializer, INotebookService, SimpleNotebookProviderInfo } from 'vs/workbench/contrib/notebook/common/notebookService'; -import { INotebookSearchService } from 'vs/workbench/contrib/search/browser/notebookSearch'; +import { INotebookSearchService } from 'vs/workbench/contrib/search/common/notebookSearch'; import { IFileMatchWithCells, ICellMatch, CellSearchModel, contentMatchesToTextSearchMatches, webviewMatchesToTextSearchMatches, genericCellMatchesToTextSearchMatches } from 'vs/workbench/contrib/search/browser/searchNotebookHelpers'; import { IEditorResolverService, priorityToRank } from 'vs/workbench/services/editor/common/editorResolverService'; -import { ITextQuery, IFileQuery, QueryType, ISearchProgressItem, ISearchComplete, ISearchConfigurationProperties, ISearchService } from 'vs/workbench/services/search/common/search'; +import { ITextQuery, QueryType, ISearchProgressItem, ISearchComplete, ISearchConfigurationProperties, IFileQuery, ISearchService } from 'vs/workbench/services/search/common/search'; import * as arrays from 'vs/base/common/arrays'; import { isNumber } from 'vs/base/common/types'; @@ -123,48 +123,67 @@ export class NotebookSearchService implements INotebookSearchService { return Array.from(uris.keys()); } - async notebookSearch(query: ITextQuery, token: CancellationToken, searchInstanceID: string, onProgress?: (result: ISearchProgressItem) => void): Promise<{ completeData: ISearchComplete; scannedFiles: ResourceSet }> { + notebookSearch(query: ITextQuery, token: CancellationToken | undefined, searchInstanceID: string, onProgress?: (result: ISearchProgressItem) => void): { + openFilesToScan: ResourceSet; + completeData: Promise; + allScannedFiles: Promise; + } { if (query.type !== QueryType.Text) { return { - completeData: { + openFilesToScan: new ResourceSet(), + completeData: Promise.resolve({ messages: [], limitHit: false, results: [], - }, - scannedFiles: new ResourceSet() + }), + allScannedFiles: Promise.resolve(new ResourceSet()), }; } - const searchStart = Date.now(); const localNotebookWidgets = this.getLocalNotebookWidgets(); const localNotebookFiles = localNotebookWidgets.map(widget => widget.viewModel!.uri); - const localResultPromise = this.getLocalNotebookResults(query, token, localNotebookWidgets, searchInstanceID); - const searchLocalEnd = Date.now(); + const getAllResults = (): { completeData: Promise; allScannedFiles: Promise } => { + const searchStart = Date.now(); - const experimentalNotebooksEnabled = this.configurationService.getValue('search').experimental?.closedNotebookRichContentResults ?? false; + const localResultPromise = this.getLocalNotebookResults(query, token ?? CancellationToken.None, localNotebookWidgets, searchInstanceID); + const searchLocalEnd = Date.now(); - let closedResultsPromise: Promise = Promise.resolve(undefined); - if (experimentalNotebooksEnabled) { - closedResultsPromise = this.getClosedNotebookResults(query, new ResourceSet(localNotebookFiles, uri => this.uriIdentityService.extUri.getComparisonKey(uri)), token); - } + const experimentalNotebooksEnabled = this.configurationService.getValue('search').experimental?.closedNotebookRichContentResults ?? false; - const resolved = (await Promise.all([localResultPromise, closedResultsPromise])).filter((result): result is INotebookSearchMatchResults => !!result); - const resultArray = resolved.map(elem => elem.results); + let closedResultsPromise: Promise = Promise.resolve(undefined); + if (experimentalNotebooksEnabled) { + closedResultsPromise = this.getClosedNotebookResults(query, new ResourceSet(localNotebookFiles, uri => this.uriIdentityService.extUri.getComparisonKey(uri)), token ?? CancellationToken.None); + } - const results = arrays.coalesce(resultArray.flatMap(map => Array.from(map.values()))); - const scannedFiles = new ResourceSet(resultArray.flatMap(map => Array.from(map.keys())), uri => this.uriIdentityService.extUri.getComparisonKey(uri)); - if (onProgress) { - results.forEach(onProgress); - } - this.logService.trace(`local notebook search time | ${searchLocalEnd - searchStart}ms`); + const promise = Promise.all([localResultPromise, closedResultsPromise]); + return { + completeData: promise.then(resolvedPromise => { + const resolved = resolvedPromise.filter((e): e is INotebookSearchMatchResults => !!e); + const resultArray = resolved.map(elem => elem.results); + const results = arrays.coalesce(resultArray.flatMap(map => Array.from(map.values()))); + if (onProgress) { + results.forEach(onProgress); + } + this.logService.trace(`local notebook search time | ${searchLocalEnd - searchStart}ms`); + return { + messages: [], + limitHit: resolved.reduce((prev, cur) => prev || cur.limitHit, false), + results, + }; + }), + allScannedFiles: promise.then(resolvedPromise => { + const resolved = resolvedPromise.filter((e): e is INotebookSearchMatchResults => !!e); + const resultArray = resolved.map(elem => elem.results); + return new ResourceSet(resultArray.flatMap(map => Array.from(map.keys())), uri => this.uriIdentityService.extUri.getComparisonKey(uri)); + }) + }; + }; + const promiseResults = getAllResults(); return { - completeData: { - messages: [], - limitHit: resolved.reduce((prev, cur) => prev || cur.limitHit, false), - results, - }, - scannedFiles + openFilesToScan: new ResourceSet(localNotebookFiles), + completeData: promiseResults.completeData, + allScannedFiles: promiseResults.allScannedFiles }; } @@ -272,10 +291,10 @@ export class NotebookSearchService implements INotebookSearchService { regex: query.contentPattern.isRegExp, wholeWord: query.contentPattern.isWordMatch, caseSensitive: query.contentPattern.isCaseSensitive, - includeMarkupInput: query.contentPattern.notebookInfo?.isInNotebookMarkdownInput, - includeMarkupPreview: query.contentPattern.notebookInfo?.isInNotebookMarkdownPreview, - includeCodeInput: query.contentPattern.notebookInfo?.isInNotebookCellInput, - includeOutput: query.contentPattern.notebookInfo?.isInNotebookCellOutput, + includeMarkupInput: query.contentPattern.notebookInfo?.isInNotebookMarkdownInput ?? true, + includeMarkupPreview: query.contentPattern.notebookInfo?.isInNotebookMarkdownPreview ?? true, + includeCodeInput: query.contentPattern.notebookInfo?.isInNotebookCellInput ?? true, + includeOutput: query.contentPattern.notebookInfo?.isInNotebookCellOutput ?? true, }, token, false, true, searchID); diff --git a/src/vs/workbench/contrib/search/browser/quickTextSearch/textSearchQuickAccess.ts b/src/vs/workbench/contrib/search/browser/quickTextSearch/textSearchQuickAccess.ts index ad3d5da68ff..15a82a6cf6a 100644 --- a/src/vs/workbench/contrib/search/browser/quickTextSearch/textSearchQuickAccess.ts +++ b/src/vs/workbench/contrib/search/browser/quickTextSearch/textSearchQuickAccess.ts @@ -12,12 +12,12 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { ILabelService } from 'vs/platform/label/common/label'; import { WorkbenchCompressibleObjectTree, getSelectionKeyboardEvent } from 'vs/platform/list/browser/listService'; -import { IPickerQuickAccessItem, PickerQuickAccessProvider } from 'vs/platform/quickinput/browser/pickerQuickAccess'; -import { IQuickPickSeparator } from 'vs/platform/quickinput/common/quickInput'; +import { FastAndSlowPicks, IPickerQuickAccessItem, PickerQuickAccessProvider, Picks } from 'vs/platform/quickinput/browser/pickerQuickAccess'; +import { IQuickPickItem, IQuickPickSeparator } from 'vs/platform/quickinput/common/quickInput'; import { IWorkspaceContextService, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; import { IViewsService } from 'vs/workbench/common/views'; import { searchDetailsIcon, searchOpenInFileIcon } from 'vs/workbench/contrib/search/browser/searchIcons'; -import { Match, MatchInNotebook, RenderableMatch, SearchModel, SearchResult } from 'vs/workbench/contrib/search/browser/searchModel'; +import { FileMatch, Match, MatchInNotebook, RenderableMatch, SearchModel, searchComparer } from 'vs/workbench/contrib/search/browser/searchModel'; import { SearchView, getEditorSelectionFromMatch } from 'vs/workbench/contrib/search/browser/searchView'; import { getOutOfWorkspaceEditorResources } from 'vs/workbench/contrib/search/common/search'; import { ACTIVE_GROUP, IEditorService } from 'vs/workbench/services/editor/common/editorService'; @@ -75,8 +75,10 @@ export class TextSearchQuickAccess extends PickerQuickAccessProvider('search'); } - private async doSearch(contentPattern: string): Promise { - + private doSearch(contentPattern: string, token: CancellationToken): { + syncResults: FileMatch[]; + asyncResults: Promise; + } | undefined { if (contentPattern === '') { return undefined; } @@ -89,8 +91,16 @@ export class TextSearchQuickAccess extends PickerQuickAccessProvider folder.uri), this._getTextQueryBuilderOptions(charsPerLine)); - await this.searchModel.search(query, undefined); - return this.searchModel.searchResult; + const result = this.searchModel.search(query, undefined, token); + + const getAsyncResults = async () => { + await result.asyncResults; + return this.searchModel.searchResult.matches().filter(e => result.syncResults.indexOf(e) === -1); + }; + return { + syncResults: this.searchModel.searchResult.matches(), + asyncResults: getAsyncResults() + }; } private moveToSearchViewlet(model: SearchModel, currentElem: RenderableMatch) { @@ -107,31 +117,24 @@ export class TextSearchQuickAccess extends PickerQuickAccessProvider { - - const searchResult = await this.doSearch(contentPattern); - - if (!searchResult) { - return []; - } + private _getPicksFromMatches(matches: FileMatch[], limit: number): (IQuickPickSeparator | IPickerQuickAccessItem)[] { + matches = matches.sort(searchComparer); + const files = matches.length > limit ? matches.slice(0, limit) : matches; const picks: Array = []; - const matches = searchResult.matches(); - const files = matches.length > MAX_FILES_SHOWN ? matches.slice(0, MAX_FILES_SHOWN) : matches; - for (let fileIndex = 0; fileIndex < matches.length; fileIndex++) { - if (fileIndex === MAX_FILES_SHOWN) { + if (fileIndex === limit) { picks.push({ type: 'separator', }); picks.push({ - label: 'See More Files', + label: localize('QuickSearchSeeMoreFiles', "See More Files"), iconClass: ThemeIcon.asClassName(searchDetailsIcon), accept: async () => { - this.moveToSearchViewlet(this.searchModel, matches[MAX_FILES_SHOWN]); + this.moveToSearchViewlet(this.searchModel, matches[limit]); } }); break; @@ -159,7 +162,7 @@ export class TextSearchQuickAccess extends PickerQuickAccessProvider { this.moveToSearchViewlet(this.searchModel, element); @@ -173,10 +176,10 @@ export class TextSearchQuickAccess extends PickerQuickAccessProvider | Promise | FastAndSlowPicks> | FastAndSlowPicks | null { + const allMatches = this.doSearch(contentPattern, token); + + if (!allMatches) { + return null; + } + const matches = allMatches.syncResults; + const syncResult = this._getPicksFromMatches(matches, MAX_FILES_SHOWN); + + if (matches.length >= MAX_FILES_SHOWN) { + return syncResult; } - return picks; + return { + picks: syncResult, + additionalPicks: allMatches.asyncResults.then((asyncResults) => { + return this._getPicksFromMatches(asyncResults, MAX_FILES_SHOWN - matches.length); + }) + }; } } diff --git a/src/vs/workbench/contrib/search/browser/replaceService.ts b/src/vs/workbench/contrib/search/browser/replaceService.ts index d45d1f289ed..8dd187bff0a 100644 --- a/src/vs/workbench/contrib/search/browser/replaceService.ts +++ b/src/vs/workbench/contrib/search/browser/replaceService.ts @@ -11,7 +11,7 @@ import { IReplaceService } from 'vs/workbench/contrib/search/browser/replace'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IModelService } from 'vs/editor/common/services/model'; import { ILanguageService } from 'vs/editor/common/languages/language'; -import { Match, FileMatch, FileMatchOrMatch, ISearchWorkbenchService, MatchInNotebook } from 'vs/workbench/contrib/search/browser/searchModel'; +import { Match, FileMatch, FileMatchOrMatch, ISearchViewModelWorkbenchService, MatchInNotebook } from 'vs/workbench/contrib/search/browser/searchModel'; import { IProgress, IProgressStep } from 'vs/platform/progress/common/progress'; import { ITextModelService, ITextModelContentProvider } from 'vs/editor/common/services/resolverService'; import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; @@ -63,7 +63,7 @@ class ReplacePreviewModel extends Disposable { @ILanguageService private readonly languageService: ILanguageService, @ITextModelService private readonly textModelResolverService: ITextModelService, @IReplaceService private readonly replaceService: IReplaceService, - @ISearchWorkbenchService private readonly searchWorkbenchService: ISearchWorkbenchService + @ISearchViewModelWorkbenchService private readonly searchWorkbenchService: ISearchViewModelWorkbenchService ) { super(); } diff --git a/src/vs/workbench/contrib/search/browser/search.contribution.ts b/src/vs/workbench/contrib/search/browser/search.contribution.ts index 0aa08eff74d..a48332a48f2 100644 --- a/src/vs/workbench/contrib/search/browser/search.contribution.ts +++ b/src/vs/workbench/contrib/search/browser/search.contribution.ts @@ -27,7 +27,7 @@ import { SearchView } from 'vs/workbench/contrib/search/browser/searchView'; import { registerContributions as searchWidgetContributions } from 'vs/workbench/contrib/search/browser/searchWidget'; import { SymbolsQuickAccessProvider } from 'vs/workbench/contrib/search/browser/symbolsQuickAccess'; import { ISearchHistoryService, SearchHistoryService } from 'vs/workbench/contrib/search/common/searchHistoryService'; -import { ISearchWorkbenchService, SearchWorkbenchService } from 'vs/workbench/contrib/search/browser/searchModel'; +import { ISearchViewModelWorkbenchService, SearchViewModelWorkbenchService } from 'vs/workbench/contrib/search/browser/searchModel'; import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle'; import { SearchSortOrder, SEARCH_EXCLUDE_CONFIG, VIEWLET_ID, ViewMode, VIEW_ID } from 'vs/workbench/services/search/common/search'; import { Extensions, IConfigurationMigrationRegistry } from 'vs/workbench/common/configuration'; @@ -45,7 +45,7 @@ import 'vs/workbench/contrib/search/browser/searchActionsTopBar'; import 'vs/workbench/contrib/search/browser/searchActionsTextQuickAccess'; import { TEXT_SEARCH_QUICK_ACCESS_PREFIX, TextSearchQuickAccess } from 'vs/workbench/contrib/search/browser/quickTextSearch/textSearchQuickAccess'; -registerSingleton(ISearchWorkbenchService, SearchWorkbenchService, InstantiationType.Delayed); +registerSingleton(ISearchViewModelWorkbenchService, SearchViewModelWorkbenchService, InstantiationType.Delayed); registerSingleton(ISearchHistoryService, SearchHistoryService, InstantiationType.Delayed); replaceContributions(); diff --git a/src/vs/workbench/contrib/search/browser/searchModel.ts b/src/vs/workbench/contrib/search/browser/searchModel.ts index 82bf57c7636..95a4644baf4 100644 --- a/src/vs/workbench/contrib/search/browser/searchModel.ts +++ b/src/vs/workbench/contrib/search/browser/searchModel.ts @@ -36,9 +36,9 @@ import { CellFindMatchWithIndex, CellWebviewFindMatch, ICellViewModel } from 'vs import { NotebookEditorWidget } from 'vs/workbench/contrib/notebook/browser/notebookEditorWidget'; import { INotebookEditorService } from 'vs/workbench/contrib/notebook/browser/services/notebookEditorService'; import { NotebookCellsChangeType } from 'vs/workbench/contrib/notebook/common/notebookCommon'; -import { INotebookSearchService } from 'vs/workbench/contrib/search/browser/notebookSearch'; import { IReplaceService } from 'vs/workbench/contrib/search/browser/replace'; import { CellSearchModel, ICellMatch, contentMatchesToTextSearchMatches, isIFileMatchWithCells, rawCellPrefix, webviewMatchesToTextSearchMatches } from 'vs/workbench/contrib/search/browser/searchNotebookHelpers'; +import { INotebookSearchService } from 'vs/workbench/contrib/search/common/notebookSearch'; import { ReplacePattern } from 'vs/workbench/services/search/common/replace'; import { IFileMatch, IPatternInfo, ISearchComplete, ISearchConfigurationProperties, ISearchProgressItem, ISearchRange, ISearchService, ITextQuery, ITextSearchContext, ITextSearchMatch, ITextSearchPreviewOptions, ITextSearchResult, ITextSearchStats, OneLineRange, resultIsMatch, SearchCompletionExitCode, SearchSortOrder } from 'vs/workbench/services/search/common/search'; import { addContextToEditorMatches, editorMatchesToTextSearchResults } from 'vs/workbench/services/search/common/searchHelpers'; @@ -2002,34 +2002,63 @@ export class SearchModel extends Disposable { this._searchResultChangedListener = this._register(this._searchResult.onChange((e) => this._onSearchResultChanged.fire(e))); } - private async doSearch(query: ITextQuery, progressEmitter: Emitter, searchQuery: ITextQuery, searchInstanceID: string, onProgress?: (result: ISearchProgressItem) => void): Promise { - const searchStart = Date.now(); - const tokenSource = this.currentCancelTokenSource = new CancellationTokenSource(); - const onProgressCall = (p: ISearchProgressItem) => { + + private doSearch(query: ITextQuery, progressEmitter: Emitter, searchQuery: ITextQuery, searchInstanceID: string, onProgress?: (result: ISearchProgressItem) => void, callerToken?: CancellationToken): { + asyncResults: Promise; + syncResults: IFileMatch[]; + } { + const asyncGenerateOnProgress = async (p: ISearchProgressItem) => { progressEmitter.fire(); this.onSearchProgress(p, searchInstanceID); - onProgress?.(p); }; - const notebookResult = await this.notebookSearchService.notebookSearch(query, this.currentCancelTokenSource.token, searchInstanceID, onProgressCall); - const currentResult = await this.searchService.textSearch( + + const syncGenerateOnProgress = (p: ISearchProgressItem) => { + progressEmitter.fire(); + this.onSearchProgress(p, searchInstanceID, true); + onProgress?.(p); + }; + const tokenSource = this.currentCancelTokenSource = new CancellationTokenSource(callerToken); + + const notebookResult = this.notebookSearchService.notebookSearch(query, tokenSource.token, searchInstanceID, syncGenerateOnProgress); + const textResult = this.searchService.textSearchSplitSyncAsync( searchQuery, - this.currentCancelTokenSource.token, onProgressCall, - notebookResult?.scannedFiles + this.currentCancelTokenSource.token, asyncGenerateOnProgress, + notebookResult.openFilesToScan, + notebookResult.allScannedFiles, ); - tokenSource.dispose(); - const searchLength = Date.now() - searchStart; - this.logService.trace(`whole search time | ${searchLength}ms`); + + const syncResults = textResult.syncResults.results; + syncResults.forEach(p => { if (p) { syncGenerateOnProgress(p); } }); + + const getAsyncResults = async (): Promise => { + const searchStart = Date.now(); + + // resolve async parts of search + const allClosedEditorResults = await textResult.asyncResults; + const resolvedNotebookResults = await notebookResult.completeData; + tokenSource.dispose(); + const searchLength = Date.now() - searchStart; + const resolvedResult = { + results: [...allClosedEditorResults.results, ...resolvedNotebookResults.results], + messages: [...allClosedEditorResults.messages, ...resolvedNotebookResults.messages], + limitHit: allClosedEditorResults.limitHit || resolvedNotebookResults.limitHit, + exit: allClosedEditorResults.exit, + stats: allClosedEditorResults.stats, + }; + this.logService.trace(`whole search time | ${searchLength}ms`); + return resolvedResult; + }; return { - results: currentResult.results.concat(notebookResult.completeData.results), - messages: currentResult.messages.concat(notebookResult.completeData.messages), - limitHit: currentResult.limitHit || notebookResult.completeData.limitHit, - exit: currentResult.exit, - stats: currentResult.stats, + asyncResults: getAsyncResults(), + syncResults }; } - async search(query: ITextQuery, onProgress?: (result: ISearchProgressItem) => void): Promise { + search(query: ITextQuery, onProgress?: (result: ISearchProgressItem) => void, callerToken?: CancellationToken): { + asyncResults: Promise; + syncResults: IFileMatch[]; + } { this.cancelSearch(true); this._searchQuery = query; @@ -2046,11 +2075,21 @@ export class SearchModel extends Disposable { // In search on type case, delay the streaming of results just a bit, so that we don't flash the only "local results" fast path this._startStreamDelay = new Promise(resolve => setTimeout(resolve, this.searchConfig.searchOnType ? 150 : 0)); - const currentRequest = this.doSearch(query, progressEmitter, this._searchQuery, searchInstanceID, onProgress); + const req = this.doSearch(query, progressEmitter, this._searchQuery, searchInstanceID, onProgress, callerToken); + const asyncResults = req.asyncResults; + const syncResults = req.syncResults; + + if (onProgress) { + syncResults.forEach(p => { + if (p) { + onProgress(p); + } + }); + } const start = Date.now(); - Promise.race([currentRequest, Event.toPromise(progressEmitter.event)]).finally(() => { + Promise.race([asyncResults, Event.toPromise(progressEmitter.event)]).finally(() => { /* __GDPR__ "searchResultsFirstRender" : { "owner": "roblourens", @@ -2060,12 +2099,14 @@ export class SearchModel extends Disposable { this.telemetryService.publicLog('searchResultsFirstRender', { duration: Date.now() - start }); }); - currentRequest.then( + asyncResults.then( value => this.onSearchCompleted(value, Date.now() - start, searchInstanceID), e => this.onSearchError(e, Date.now() - start)); - try { - return await currentRequest; + return { + asyncResults: asyncResults, + syncResults: syncResults + }; } finally { /* __GDPR__ "searchResultsFinished" : { @@ -2131,14 +2172,23 @@ export class SearchModel extends Disposable { } } - private async onSearchProgress(p: ISearchProgressItem, searchInstanceID: string) { + private onSearchProgress(p: ISearchProgressItem, searchInstanceID: string, sync = true) { if ((p).resource) { this._resultQueue.push(p); - await this._startStreamDelay; - if (this._resultQueue.length) { - this._searchResult.add(this._resultQueue, searchInstanceID, true); - this._resultQueue.length = 0; + if (sync) { + if (this._resultQueue.length) { + this._searchResult.add(this._resultQueue, searchInstanceID, true); + this._resultQueue.length = 0; + } + } else { + this._startStreamDelay.then(() => { + if (this._resultQueue.length) { + this._searchResult.add(this._resultQueue, searchInstanceID, true); + this._resultQueue.length = 0; + } + }); } + } } @@ -2171,7 +2221,7 @@ export type FileMatchOrMatch = FileMatch | Match; export type RenderableMatch = FolderMatch | FolderMatchWithResource | FileMatch | Match; -export class SearchWorkbenchService implements ISearchWorkbenchService { +export class SearchViewModelWorkbenchService implements ISearchViewModelWorkbenchService { declare readonly _serviceBrand: undefined; private _searchModel: SearchModel | null = null; @@ -2187,9 +2237,9 @@ export class SearchWorkbenchService implements ISearchWorkbenchService { } } -export const ISearchWorkbenchService = createDecorator('searchWorkbenchService'); +export const ISearchViewModelWorkbenchService = createDecorator('searchViewModelWorkbenchService'); -export interface ISearchWorkbenchService { +export interface ISearchViewModelWorkbenchService { readonly _serviceBrand: undefined; readonly searchModel: SearchModel; diff --git a/src/vs/workbench/contrib/search/browser/searchView.ts b/src/vs/workbench/contrib/search/browser/searchView.ts index 6df2f295095..d6be8a28998 100644 --- a/src/vs/workbench/contrib/search/browser/searchView.ts +++ b/src/vs/workbench/contrib/search/browser/searchView.ts @@ -70,7 +70,7 @@ import * as Constants from 'vs/workbench/contrib/search/common/constants'; import { IReplaceService } from 'vs/workbench/contrib/search/browser/replace'; import { getOutOfWorkspaceEditorResources, SearchStateKey, SearchUIState } from 'vs/workbench/contrib/search/common/search'; import { ISearchHistoryService, ISearchHistoryValues, SearchHistoryService } from 'vs/workbench/contrib/search/common/searchHistoryService'; -import { FileMatch, FileMatchOrMatch, FolderMatch, FolderMatchWithResource, IChangeEvent, ISearchWorkbenchService, Match, MatchInNotebook, RenderableMatch, searchMatchComparer, SearchModel, SearchResult } from 'vs/workbench/contrib/search/browser/searchModel'; +import { FileMatch, FileMatchOrMatch, FolderMatch, FolderMatchWithResource, IChangeEvent, ISearchViewModelWorkbenchService, Match, MatchInNotebook, RenderableMatch, searchMatchComparer, SearchModel, SearchResult } from 'vs/workbench/contrib/search/browser/searchModel'; import { createEditorFromSearchResult } from 'vs/workbench/contrib/searchEditor/browser/searchEditorActions'; import { ACTIVE_GROUP, IEditorService, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService'; import { IPreferencesService, ISettingsEditorOptions } from 'vs/workbench/services/preferences/common/preferences'; @@ -174,7 +174,7 @@ export class SearchView extends ViewPane { @IViewDescriptorService viewDescriptorService: IViewDescriptorService, @IConfigurationService configurationService: IConfigurationService, @IWorkspaceContextService private readonly contextService: IWorkspaceContextService, - @ISearchWorkbenchService private readonly searchWorkbenchService: ISearchWorkbenchService, + @ISearchViewModelWorkbenchService private readonly searchViewModelWorkbenchService: ISearchViewModelWorkbenchService, @IContextKeyService contextKeyService: IContextKeyService, @IReplaceService private readonly replaceService: IReplaceService, @ITextFileService private readonly textFileService: ITextFileService, @@ -235,7 +235,7 @@ export class SearchView extends ViewPane { } }); - this.viewModel = this._register(this.searchWorkbenchService.searchModel); + this.viewModel = this._register(this.searchViewModelWorkbenchService.searchModel); this.queryBuilder = this.instantiationService.createInstance(QueryBuilder); this.memento = new Memento(this.id, storageService); this.viewletState = this.memento.getMemento(StorageScope.WORKSPACE, StorageTarget.MACHINE); @@ -1743,8 +1743,8 @@ export class SearchView extends ViewPane { this.tree.setSelection([]); this.tree.setFocus([]); - return this.viewModel.search(query) - .then(onComplete, onError); + const result = this.viewModel.search(query); + return result.asyncResults.then(onComplete, onError); } private onOpenSettings(e: dom.EventLike): void { diff --git a/src/vs/workbench/contrib/search/browser/notebookSearch.ts b/src/vs/workbench/contrib/search/common/notebookSearch.ts similarity index 75% rename from src/vs/workbench/contrib/search/browser/notebookSearch.ts rename to src/vs/workbench/contrib/search/common/notebookSearch.ts index 2fb52658219..5237c1bd03c 100644 --- a/src/vs/workbench/contrib/search/browser/notebookSearch.ts +++ b/src/vs/workbench/contrib/search/common/notebookSearch.ts @@ -14,5 +14,9 @@ export interface INotebookSearchService { readonly _serviceBrand: undefined; - notebookSearch(query: ITextQuery, token: CancellationToken, searchInstanceID: string, onProgress?: (result: ISearchProgressItem) => void): Promise<{ completeData: ISearchComplete; scannedFiles: ResourceSet }>; + notebookSearch(query: ITextQuery, token: CancellationToken | undefined, searchInstanceID: string, onProgress?: (result: ISearchProgressItem) => void): { + openFilesToScan: ResourceSet; + completeData: Promise; + allScannedFiles: Promise; + }; } diff --git a/src/vs/workbench/contrib/search/test/browser/searchModel.test.ts b/src/vs/workbench/contrib/search/test/browser/searchModel.test.ts index 0adcb1e47d4..ca0a09f0c31 100644 --- a/src/vs/workbench/contrib/search/test/browser/searchModel.test.ts +++ b/src/vs/workbench/contrib/search/test/browser/searchModel.test.ts @@ -14,7 +14,7 @@ import { ModelService } from 'vs/editor/common/services/modelService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService'; import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock'; -import { IFileMatch, IFileQuery, IFileSearchStats, IFolderQuery, ISearchComplete, ISearchProgressItem, ISearchQuery, ISearchService, ITextSearchMatch, OneLineRange, QueryType, TextSearchMatch } from 'vs/workbench/services/search/common/search'; +import { IFileMatch, IFileQuery, IFileSearchStats, IFolderQuery, ISearchComplete, ISearchProgressItem, ISearchQuery, ISearchService, ITextQuery, ITextSearchMatch, OneLineRange, QueryType, TextSearchMatch } from 'vs/workbench/services/search/common/search'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils'; import { CellMatch, MatchInNotebook, SearchModel } from 'vs/workbench/contrib/search/browser/searchModel'; @@ -36,7 +36,7 @@ import { ICellViewModel } from 'vs/workbench/contrib/notebook/browser/notebookBr import { FindMatch, IReadonlyTextBuffer } from 'vs/editor/common/model'; import { ResourceMap, ResourceSet } from 'vs/base/common/map'; import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; -import { INotebookSearchService } from 'vs/workbench/contrib/search/browser/notebookSearch'; +import { INotebookSearchService } from 'vs/workbench/contrib/search/common/notebookSearch'; const nullEvent = new class { id: number = -1; @@ -112,6 +112,20 @@ suite('SearchModel', () => { }); }); + }, + textSearchSplitSyncAsync(query: ITextQuery, token?: CancellationToken | undefined, onProgress?: ((result: ISearchProgressItem) => void) | undefined): { syncResults: ISearchComplete; asyncResults: Promise } { + return { + syncResults: { + results: [], + messages: [] + }, + asyncResults: new Promise(resolve => { + queueMicrotask(() => { + results.forEach(onProgress!); + resolve(complete!); + }); + }) + }; } }; } @@ -129,6 +143,17 @@ suite('SearchModel', () => { reject(error); }); }); + }, + textSearchSplitSyncAsync(query: ITextQuery, token?: CancellationToken | undefined, onProgress?: ((result: ISearchProgressItem) => void) | undefined): { syncResults: ISearchComplete; asyncResults: Promise } { + return { + syncResults: { + results: [], + messages: [] + }, + asyncResults: new Promise((resolve, reject) => { + reject(error); + }) + }; } }; } @@ -151,16 +176,47 @@ suite('SearchModel', () => { resolve({}); }); }); + }, + textSearchSplitSyncAsync(query: ITextQuery, token?: CancellationToken | undefined, onProgress?: ((result: ISearchProgressItem) => void) | undefined): { syncResults: ISearchComplete; asyncResults: Promise } { + token?.onCancellationRequested(() => tokenSource.cancel()); + return { + syncResults: { + results: [], + messages: [] + }, + asyncResults: new Promise(resolve => { + queueMicrotask(() => { + resolve({}); + }); + }) + }; + } + }; + } + + function searchServiceWithDeferredPromise(p: Promise): ISearchService { + return { + textSearchSplitSyncAsync(query: ITextQuery, token?: CancellationToken | undefined, onProgress?: ((result: ISearchProgressItem) => void) | undefined): { syncResults: ISearchComplete; asyncResults: Promise } { + return { + syncResults: { + results: [], + messages: [] + }, + asyncResults: p, + }; } }; } - function notebookSearchServiceWithInfo(results: IFileMatchWithCells[], tokenSource: CancellationTokenSource | undefined): INotebookSearchService { return { _serviceBrand: undefined, - notebookSearch(query: ISearchQuery, token: CancellationToken, searchInstanceID: string, onProgress?: (result: ISearchProgressItem) => void, notebookURIs?: ResourceSet): Promise<{ completeData: ISearchComplete; scannedFiles: ResourceSet }> { + notebookSearch(query: ITextQuery, token: CancellationToken | undefined, searchInstanceID: string, onProgress?: (result: ISearchProgressItem) => void): { + openFilesToScan: ResourceSet; + completeData: Promise; + allScannedFiles: Promise; + } { token?.onCancellationRequested(() => tokenSource?.cancel()); const localResults = new ResourceMap(uri => uri.path); @@ -171,15 +227,15 @@ suite('SearchModel', () => { if (onProgress) { arrays.coalesce([...localResults.values()]).forEach(onProgress); } - return Promise.resolve( - { - completeData: { - messages: [], - results: arrays.coalesce([...localResults.values()]), - limitHit: false - }, - scannedFiles: new ResourceSet([...localResults.keys()]), - }); + return { + openFilesToScan: new ResourceSet([...localResults.keys()]), + completeData: Promise.resolve({ + messages: [], + results: arrays.coalesce([...localResults.values()]), + limitHit: false + }), + allScannedFiles: Promise.resolve(new ResourceSet()), + }; } }; } @@ -194,7 +250,7 @@ suite('SearchModel', () => { instantiationService.stub(INotebookSearchService, notebookSearchServiceWithInfo([], undefined)); const testObject: SearchModel = instantiationService.createInstance(SearchModel); - await testObject.search({ contentPattern: { pattern: 'somestring' }, type: QueryType.Text, folderQueries }); + await testObject.search({ contentPattern: { pattern: 'somestring' }, type: QueryType.Text, folderQueries }).asyncResults; const actual = testObject.searchResult.matches(); @@ -216,17 +272,14 @@ suite('SearchModel', () => { test('Search Model: Search can return notebook results', async () => { - const notebookUri = createFileUriFromPathFromRoot('/1'); - const results = [ aRawMatch('/2', new TextSearchMatch('test', new OneLineRange(1, 1, 5)), new TextSearchMatch('this is a test', new OneLineRange(1, 11, 15))), aRawMatch('/3', new TextSearchMatch('test', lineOneRange))]; - const searchService = instantiationService.stub(ISearchService, searchServiceWithResults(results, { limitHit: false, messages: [], results })); + instantiationService.stub(ISearchService, searchServiceWithResults(results, { limitHit: false, messages: [], results })); sinon.stub(CellMatch.prototype, 'addContext'); - const textSearch = sinon.spy(searchService, 'textSearch'); const mdInputCell = { cellKind: CellKind.Markup, textBuffer: { getLineContent(lineNumber: number): string { @@ -297,12 +350,10 @@ suite('SearchModel', () => { const notebookSearchService = instantiationService.stub(INotebookSearchService, notebookSearchServiceWithInfo([aRawMatchWithCells('/1', cellMatchMd, cellMatchCode)], undefined)); const notebookSearch = sinon.spy(notebookSearchService, "notebookSearch"); const model: SearchModel = instantiationService.createInstance(SearchModel); - await model.search({ contentPattern: { pattern: 'test' }, type: QueryType.Text, folderQueries }); + await model.search({ contentPattern: { pattern: 'test' }, type: QueryType.Text, folderQueries }).asyncResults; const actual = model.searchResult.matches(); assert(notebookSearch.calledOnce); - assert(textSearch.getCall(0).args[3]?.size === 1); - assert(textSearch.getCall(0).args[3]?.has(notebookUri)); // ensure that the textsearch knows not to re-source the notebooks assert.strictEqual(3, actual.length); assert.strictEqual(URI.file(`${getRootName()}/1`).toString(), actual[0].resource.toString()); @@ -351,7 +402,7 @@ suite('SearchModel', () => { instantiationService.stub(INotebookSearchService, notebookSearchServiceWithInfo([], undefined)); const testObject: SearchModel = instantiationService.createInstance(SearchModel); - await testObject.search({ contentPattern: { pattern: 'somestring' }, type: QueryType.Text, folderQueries }); + await testObject.search({ contentPattern: { pattern: 'somestring' }, type: QueryType.Text, folderQueries }).asyncResults; assert.ok(target.calledThrice); assert.ok(target.calledWith('searchResultsFirstRender')); @@ -368,7 +419,7 @@ suite('SearchModel', () => { instantiationService.stub(INotebookSearchService, notebookSearchServiceWithInfo([], undefined)); const testObject = instantiationService.createInstance(SearchModel); - const result = testObject.search({ contentPattern: { pattern: 'somestring' }, type: QueryType.Text, folderQueries }); + const result = testObject.search({ contentPattern: { pattern: 'somestring' }, type: QueryType.Text, folderQueries }).asyncResults; return result.then(() => { return timeout(1).then(() => { @@ -390,7 +441,7 @@ suite('SearchModel', () => { instantiationService.stub(INotebookSearchService, notebookSearchServiceWithInfo([], undefined)); const testObject = instantiationService.createInstance(SearchModel); - const result = testObject.search({ contentPattern: { pattern: 'somestring' }, type: QueryType.Text, folderQueries }); + const result = testObject.search({ contentPattern: { pattern: 'somestring' }, type: QueryType.Text, folderQueries }).asyncResults; return result.then(() => { return timeout(1).then(() => { @@ -410,15 +461,15 @@ suite('SearchModel', () => { instantiationService.stub(ITelemetryService, 'publicLog', target1); instantiationService.stub(ISearchService, searchServiceWithError(new Error('error'))); + instantiationService.stub(INotebookSearchService, notebookSearchServiceWithInfo([], undefined)); const testObject = instantiationService.createInstance(SearchModel); - const result = testObject.search({ contentPattern: { pattern: 'somestring' }, type: QueryType.Text, folderQueries }); + const result = testObject.search({ contentPattern: { pattern: 'somestring' }, type: QueryType.Text, folderQueries }).asyncResults; return result.then(() => { }, () => { return timeout(1).then(() => { assert.ok(target1.calledWith('searchResultsFirstRender')); assert.ok(target1.calledWith('searchResultsFinished')); - // assert.ok(target2.calledOnce); }); }); }); @@ -430,14 +481,16 @@ suite('SearchModel', () => { instantiationService.stub(ITelemetryService, 'publicLog', target1); const deferredPromise = new DeferredPromise(); - instantiationService.stub(ISearchService, 'textSearch', deferredPromise.p); + + instantiationService.stub(ISearchService, searchServiceWithDeferredPromise(deferredPromise.p)); + instantiationService.stub(INotebookSearchService, notebookSearchServiceWithInfo([], undefined)); const testObject = instantiationService.createInstance(SearchModel); - const result = testObject.search({ contentPattern: { pattern: 'somestring' }, type: QueryType.Text, folderQueries }); + const result = testObject.search({ contentPattern: { pattern: 'somestring' }, type: QueryType.Text, folderQueries }).asyncResults; deferredPromise.cancel(); - return result.then(() => { }, () => { + return result.then(() => { }, async () => { return timeout(1).then(() => { assert.ok(target1.calledWith('searchResultsFirstRender')); assert.ok(target1.calledWith('searchResultsFinished')); @@ -456,7 +509,7 @@ suite('SearchModel', () => { instantiationService.stub(ISearchService, searchServiceWithResults(results, { limitHit: false, messages: [], results: [] })); instantiationService.stub(INotebookSearchService, notebookSearchServiceWithInfo([], undefined)); const testObject: SearchModel = instantiationService.createInstance(SearchModel); - await testObject.search({ contentPattern: { pattern: 'somestring' }, type: QueryType.Text, folderQueries }); + await testObject.search({ contentPattern: { pattern: 'somestring' }, type: QueryType.Text, folderQueries }).asyncResults; assert.ok(!testObject.searchResult.isEmpty()); instantiationService.stub(ISearchService, searchServiceWithResults([])); @@ -487,24 +540,24 @@ suite('SearchModel', () => { instantiationService.stub(INotebookSearchService, notebookSearchServiceWithInfo([], undefined)); const testObject: SearchModel = instantiationService.createInstance(SearchModel); - await testObject.search({ contentPattern: { pattern: 're' }, type: QueryType.Text, folderQueries }); + await testObject.search({ contentPattern: { pattern: 're' }, type: QueryType.Text, folderQueries }).asyncResults; testObject.replaceString = 'hello'; let match = testObject.searchResult.matches()[0].matches()[0]; assert.strictEqual('hello', match.replaceString); - await testObject.search({ contentPattern: { pattern: 're', isRegExp: true }, type: QueryType.Text, folderQueries }); + await testObject.search({ contentPattern: { pattern: 're', isRegExp: true }, type: QueryType.Text, folderQueries }).asyncResults; match = testObject.searchResult.matches()[0].matches()[0]; assert.strictEqual('hello', match.replaceString); - await testObject.search({ contentPattern: { pattern: 're(?:vi)', isRegExp: true }, type: QueryType.Text, folderQueries }); + await testObject.search({ contentPattern: { pattern: 're(?:vi)', isRegExp: true }, type: QueryType.Text, folderQueries }).asyncResults; match = testObject.searchResult.matches()[0].matches()[0]; assert.strictEqual('hello', match.replaceString); - await testObject.search({ contentPattern: { pattern: 'r(e)(?:vi)', isRegExp: true }, type: QueryType.Text, folderQueries }); + await testObject.search({ contentPattern: { pattern: 'r(e)(?:vi)', isRegExp: true }, type: QueryType.Text, folderQueries }).asyncResults; match = testObject.searchResult.matches()[0].matches()[0]; assert.strictEqual('hello', match.replaceString); - await testObject.search({ contentPattern: { pattern: 'r(e)(?:vi)', isRegExp: true }, type: QueryType.Text, folderQueries }); + await testObject.search({ contentPattern: { pattern: 'r(e)(?:vi)', isRegExp: true }, type: QueryType.Text, folderQueries }).asyncResults; testObject.replaceString = 'hello$1'; match = testObject.searchResult.matches()[0].matches()[0]; assert.strictEqual('helloe', match.replaceString); diff --git a/src/vs/workbench/contrib/searchEditor/browser/searchEditor.ts b/src/vs/workbench/contrib/searchEditor/browser/searchEditor.ts index 783e8bea1dc..e9bc0f046cd 100644 --- a/src/vs/workbench/contrib/searchEditor/browser/searchEditor.ts +++ b/src/vs/workbench/contrib/searchEditor/browser/searchEditor.ts @@ -567,8 +567,8 @@ export class SearchEditor extends AbstractTextCodeEditor const { configurationModel } = await startInput.resolveModels(); configurationModel.updateConfig(config); - - startInput.ongoingSearchOperation = this.searchModel.search(query).finally(() => { + const result = this.searchModel.search(query); + startInput.ongoingSearchOperation = result.asyncResults.finally(() => { this.ongoingOperations--; if (this.ongoingOperations === 0) { this.searchOperation.stop(); diff --git a/src/vs/workbench/services/search/common/search.ts b/src/vs/workbench/services/search/common/search.ts index 1702df60753..caded264a85 100644 --- a/src/vs/workbench/services/search/common/search.ts +++ b/src/vs/workbench/services/search/common/search.ts @@ -19,6 +19,7 @@ import * as paths from 'vs/base/common/path'; import { isCancellationError } from 'vs/base/common/errors'; import { TextSearchCompleteMessageType } from 'vs/workbench/services/search/common/searchExtTypes'; import { isThenable } from 'vs/base/common/async'; +import { ResourceSet } from 'vs/base/common/map'; export { TextSearchCompleteMessageType }; @@ -41,7 +42,8 @@ export const ISearchService = createDecorator('searchService'); */ export interface ISearchService { readonly _serviceBrand: undefined; - textSearch(query: ITextQuery, token?: CancellationToken, onProgress?: (result: ISearchProgressItem) => void, notebookURIs?: Set): Promise; + textSearch(query: ITextQuery, token?: CancellationToken, onProgress?: (result: ISearchProgressItem) => void): Promise; + textSearchSplitSyncAsync(query: ITextQuery, token?: CancellationToken | undefined, onProgress?: ((result: ISearchProgressItem) => void) | undefined, notebookFilesToIgnore?: ResourceSet, asyncNotebookFilesToIgnore?: Promise): { syncResults: ISearchComplete; asyncResults: Promise }; fileSearch(query: IFileQuery, token?: CancellationToken): Promise; clearCache(cacheKey: string): Promise; registerSearchResultProvider(scheme: string, type: SearchProviderType, provider: ISearchResultProvider): IDisposable; diff --git a/src/vs/workbench/services/search/common/searchService.ts b/src/vs/workbench/services/search/common/searchService.ts index 63b1c192a86..bbabce133c8 100644 --- a/src/vs/workbench/services/search/common/searchService.ts +++ b/src/vs/workbench/services/search/common/searchService.ts @@ -73,37 +73,63 @@ export class SearchService extends Disposable implements ISearchService { }); } - async textSearch(query: ITextQuery, token?: CancellationToken, onProgress?: (item: ISearchProgressItem) => void, notebookURIs?: ResourceSet): Promise { - // Get local results from dirty/untitled - const localResults = this.getLocalResults(query); + async textSearch(query: ITextQuery, token?: CancellationToken, onProgress?: (item: ISearchProgressItem) => void): Promise { + const results = this.textSearchSplitSyncAsync(query, token, onProgress); + const openEditorResults = results.syncResults; + const otherResults = await results.asyncResults; + return { + limitHit: otherResults.limitHit || openEditorResults.limitHit, + results: [...otherResults.results, ...openEditorResults.results], + messages: [...otherResults.messages, ...openEditorResults.messages] + }; + } + + textSearchSplitSyncAsync( + query: ITextQuery, + token?: CancellationToken | undefined, + onProgress?: ((result: ISearchProgressItem) => void) | undefined, + notebookFilesToIgnore?: ResourceSet, + asyncNotebookFilesToIgnore?: Promise + ): { + syncResults: ISearchComplete; + asyncResults: Promise; + } { + // Get open editor results from dirty/untitled + const openEditorResults = this.getOpenEditorResults(query); if (onProgress) { - arrays.coalesce([...localResults.results.values()]).forEach(onProgress); + arrays.coalesce([...openEditorResults.results.values()]).filter(e => !(notebookFilesToIgnore && notebookFilesToIgnore.has(e.resource))).forEach(onProgress); } - const onProviderProgress = (progress: ISearchProgressItem) => { - if (isFileMatch(progress)) { - // Match - if (!localResults.results.has(progress.resource) && !(notebookURIs && notebookURIs.has(progress.resource)) && onProgress) { // don't override local results - onProgress(progress); + const syncResults: ISearchComplete = { + results: arrays.coalesce([...openEditorResults.results.values()]), + limitHit: openEditorResults.limitHit ?? false, + messages: [] + }; + + const getAsyncResults = async () => { + const resolvedAsyncNotebookFilesToIgnore = await asyncNotebookFilesToIgnore ?? new ResourceSet(); + const onProviderProgress = (progress: ISearchProgressItem) => { + if (isFileMatch(progress)) { + // Match + if (!openEditorResults.results.has(progress.resource) && !resolvedAsyncNotebookFilesToIgnore.has(progress.resource) && onProgress) { // don't override open editor results + onProgress(progress); + } + } else if (onProgress) { + // Progress + onProgress(progress); } - } else if (onProgress) { - // Progress - onProgress(progress); - } - if (isProgressMessage(progress)) { - this.logService.debug('SearchService#search', progress.message); - } + if (isProgressMessage(progress)) { + this.logService.debug('SearchService#search', progress.message); + } + }; + return await this.doSearch(query, token, onProviderProgress); }; - const otherResults = await this.doSearch(query, token, onProviderProgress); return { - ...otherResults, - ...{ - limitHit: otherResults.limitHit || localResults.limitHit - }, - results: [...otherResults.results, ...arrays.coalesce([...localResults.results.values()])] + syncResults, + asyncResults: getAsyncResults() }; } @@ -404,8 +430,8 @@ export class SearchService extends Disposable implements ISearchService { } } - private getLocalResults(query: ITextQuery): { results: ResourceMap; limitHit: boolean } { - const localResults = new ResourceMap(uri => this.uriIdentityService.extUri.getComparisonKey(uri)); + private getOpenEditorResults(query: ITextQuery): { results: ResourceMap; limitHit: boolean } { + const openEditorResults = new ResourceMap(uri => this.uriIdentityService.extUri.getComparisonKey(uri)); let limitHit = false; if (query.type === QueryType.Text) { @@ -465,18 +491,18 @@ export class SearchService extends Disposable implements ISearchService { } const fileMatch = new FileMatch(originalResource); - localResults.set(originalResource, fileMatch); + openEditorResults.set(originalResource, fileMatch); const textSearchResults = editorMatchesToTextSearchResults(matches, model, query.previewOptions); fileMatch.results = addContextToEditorMatches(textSearchResults, model, query); } else { - localResults.set(originalResource, null); + openEditorResults.set(originalResource, null); } }); } return { - results: localResults, + results: openEditorResults, limitHit }; } From ca2c1636f87ea4705f32345c2e348e815996e129 Mon Sep 17 00:00:00 2001 From: Henning Dieterichs Date: Wed, 23 Aug 2023 17:09:57 +0200 Subject: [PATCH 123/221] Improves moved code detection feature --- .../diffEditorDecorations.ts | 15 +- .../diffEditorWidget2/diffEditorViewModel.ts | 28 ++- .../diffEditorWidget2.contribution.ts | 27 +++ .../diffEditorWidget2/diffEditorWidget2.ts | 25 ++- .../widget/diffEditorWidget2/lineAlignment.ts | 6 +- .../diffEditorWidget2/movedBlocksLines.ts | 164 ++++++++++++++++-- .../widget/diffEditorWidget2/style.css | 16 ++ .../browser/widget/diffEditorWidget2/utils.ts | 3 + src/vs/editor/common/editorContextKeys.ts | 1 + 9 files changed, 245 insertions(+), 40 deletions(-) diff --git a/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorDecorations.ts b/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorDecorations.ts index 194f37c9882..9a4b5bcf094 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorDecorations.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorDecorations.ts @@ -34,13 +34,13 @@ export class DiffEditorDecorations extends Disposable { return null; } - const currentMove = this._diffModel.read(reader)!.syncedMovedTexts.read(reader); + const movedTextToCompare = this._diffModel.read(reader)!.movedTextToCompare.read(reader); const renderIndicators = this._options.renderIndicators.read(reader); const showEmptyDecorations = this._options.showEmptyDecorations.read(reader); const originalDecorations: IModelDeltaDecoration[] = []; const modifiedDecorations: IModelDeltaDecoration[] = []; - if (!currentMove) { + if (!movedTextToCompare) { for (const m of diff.mappings) { if (!m.lineRangeMapping.originalRange.isEmpty) { originalDecorations.push({ range: m.lineRangeMapping.originalRange.toInclusiveRange()!, options: renderIndicators ? diffLineDeleteDecorationBackgroundWithIndicator : diffLineDeleteDecorationBackground }); @@ -68,14 +68,14 @@ export class DiffEditorDecorations extends Disposable { } } - if (!m.lineRangeMapping.modifiedRange.isEmpty && this._options.shouldRenderRevertArrows.read(reader) && !currentMove) { + if (!m.lineRangeMapping.modifiedRange.isEmpty && this._options.shouldRenderRevertArrows.read(reader) && !movedTextToCompare) { modifiedDecorations.push({ range: Range.fromPositions(new Position(m.lineRangeMapping.modifiedRange.startLineNumber, 1)), options: arrowRevertChange }); } } } - if (currentMove) { - for (const m of currentMove.changes) { + if (movedTextToCompare) { + for (const m of movedTextToCompare.changes) { const fullRangeOriginal = m.originalRange.toInclusiveRange(); if (fullRangeOriginal) { originalDecorations.push({ range: fullRangeOriginal, options: renderIndicators ? diffLineDeleteDecorationBackgroundWithIndicator : diffLineDeleteDecorationBackground }); @@ -91,12 +91,13 @@ export class DiffEditorDecorations extends Disposable { } } } + const activeMovedText = this._diffModel.read(reader)!.activeMovedText.read(reader); for (const m of diff.movedTexts) { originalDecorations.push({ range: m.lineRangeMapping.original.toInclusiveRange()!, options: { description: 'moved', - blockClassName: 'movedOriginal' + (m === currentMove ? ' currentMove' : ''), + blockClassName: 'movedOriginal' + (m === activeMovedText ? ' currentMove' : ''), blockPadding: [MovedBlocksLinesPart.movedCodeBlockPadding, 0, MovedBlocksLinesPart.movedCodeBlockPadding, MovedBlocksLinesPart.movedCodeBlockPadding], } }); @@ -104,7 +105,7 @@ export class DiffEditorDecorations extends Disposable { modifiedDecorations.push({ range: m.lineRangeMapping.modified.toInclusiveRange()!, options: { description: 'moved', - blockClassName: 'movedModified' + (m === currentMove ? ' currentMove' : ''), + blockClassName: 'movedModified' + (m === activeMovedText ? ' currentMove' : ''), blockPadding: [4, 0, 4, 4], } }); diff --git a/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorViewModel.ts b/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorViewModel.ts index 4927ebeb9c1..8dea4d6cc56 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorViewModel.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorViewModel.ts @@ -48,7 +48,21 @@ export class DiffEditorViewModel extends Disposable implements IDiffEditorViewMo } ); - public readonly syncedMovedTexts = observableValue('syncedMovedText', undefined); + public readonly movedTextToCompare = observableValue('movedTextToCompare', undefined); + + private readonly _activeMovedText = observableValue('activeMovedText', undefined); + private readonly _hoveredMovedText = observableValue('hoveredMovedText', undefined); + + + public readonly activeMovedText = derived(r => this.movedTextToCompare.read(r) ?? this._hoveredMovedText.read(r) ?? this._activeMovedText.read(r)); + + public setActiveMovedText(movedText: MovedText | undefined): void { + this._activeMovedText.set(movedText, undefined); + } + + public setHoveredMovedText(movedText: MovedText | undefined): void { + this._hoveredMovedText.set(movedText, undefined); + } constructor( public readonly model: IDiffEditorModel, @@ -114,8 +128,8 @@ export class DiffEditorViewModel extends Disposable implements IDiffEditorViewMo transaction(tx => { this._diff.set(DiffState.fromDiffResult(this._lastDiff!), tx); updateUnchangedRegions(result, tx); - const currentSyncedMovedText = this.syncedMovedTexts.get(); - this.syncedMovedTexts.set(currentSyncedMovedText ? this._lastDiff!.moves.find(m => m.lineRangeMapping.modified.intersect(currentSyncedMovedText.lineRangeMapping.modified)) : undefined, tx); + const currentSyncedMovedText = this.movedTextToCompare.get(); + this.movedTextToCompare.set(currentSyncedMovedText ? this._lastDiff!.moves.find(m => m.lineRangeMapping.modified.intersect(currentSyncedMovedText.lineRangeMapping.modified)) : undefined, tx); }); } } @@ -132,8 +146,8 @@ export class DiffEditorViewModel extends Disposable implements IDiffEditorViewMo transaction(tx => { this._diff.set(DiffState.fromDiffResult(this._lastDiff!), tx); updateUnchangedRegions(result, tx); - const currentSyncedMovedText = this.syncedMovedTexts.get(); - this.syncedMovedTexts.set(currentSyncedMovedText ? this._lastDiff!.moves.find(m => m.lineRangeMapping.modified.intersect(currentSyncedMovedText.lineRangeMapping.modified)) : undefined, tx); + const currentSyncedMovedText = this.movedTextToCompare.get(); + this.movedTextToCompare.set(currentSyncedMovedText ? this._lastDiff!.moves.find(m => m.lineRangeMapping.modified.intersect(currentSyncedMovedText.lineRangeMapping.modified)) : undefined, tx); }); } } @@ -180,8 +194,8 @@ export class DiffEditorViewModel extends Disposable implements IDiffEditorViewMo const state = DiffState.fromDiffResult(result); this._diff.set(state, tx); this._isDiffUpToDate.set(true, tx); - const currentSyncedMovedText = this.syncedMovedTexts.get(); - this.syncedMovedTexts.set(currentSyncedMovedText ? this._lastDiff.moves.find(m => m.lineRangeMapping.modified.intersect(currentSyncedMovedText.lineRangeMapping.modified)) : undefined, tx); + const currentSyncedMovedText = this.movedTextToCompare.get(); + this.movedTextToCompare.set(currentSyncedMovedText ? this._lastDiff.moves.find(m => m.lineRangeMapping.modified.intersect(currentSyncedMovedText.lineRangeMapping.modified)) : undefined, tx); }); })); } diff --git a/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2.contribution.ts b/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2.contribution.ts index 13c654d867f..7421abcd386 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2.contribution.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2.contribution.ts @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { Codicon } from 'vs/base/common/codicons'; +import { KeyCode } from 'vs/base/common/keyCodes'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { EditorAction2, ServicesAccessor } from 'vs/editor/browser/editorExtensions'; import { findFocusedDiffEditor } from 'vs/editor/browser/widget/diffEditor.contribution'; @@ -128,3 +129,29 @@ export class SwitchSide extends EditorAction2 { } registerAction2(SwitchSide); + +export class ExitCompareMove extends EditorAction2 { + constructor() { + super({ + id: 'diffEditor.exitCompareMove', + title: { value: localize('exitCompareMove', "Exit Compare Move"), original: 'Exit Compare Move' }, + icon: Codicon.close, + precondition: EditorContextKeys.comparingMovedCode, + f1: false, + category: diffEditorCategory, + keybinding: { + weight: 10000, + primary: KeyCode.Escape, + } + }); + } + + runEditorCommand(accessor: ServicesAccessor, editor: ICodeEditor, ...args: unknown[]): void { + const diffEditor = findFocusedDiffEditor(accessor); + if (diffEditor instanceof DiffEditorWidget2) { + diffEditor.exitCompareMove(); + } + } +} + +registerAction2(ExitCompareMove); diff --git a/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2.ts b/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2.ts index 63973ae2e03..5bc2b098e2b 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2.ts @@ -111,6 +111,12 @@ export class DiffEditorWidget2 extends DelegatingEditor implements IDiffEditor { isEmbeddedDiffEditorKey.set(this._options.isInEmbeddedEditor.read(reader)); })); + const comparingMovedCodeKey = EditorContextKeys.comparingMovedCode.bindTo(this._contextKeyService); + this._register(autorun(reader => { + /** @description update comparingMovedCodeKey */ + comparingMovedCodeKey.set(!!this._diffModel.read(reader)?.movedTextToCompare.read(reader)); + })); + const diffEditorRenderSideBySideInlineBreakpointReachedContextKeyValue = EditorContextKeys.diffEditorRenderSideBySideInlineBreakpointReached.bindTo(this._contextKeyService); this._register(autorun(reader => { /** @description update accessibleDiffViewerVisible context key */ @@ -223,19 +229,6 @@ export class DiffEditorWidget2 extends DelegatingEditor implements IDiffEditor { ), })); - this._register(this._editors.original.onDidChangeCursorPosition(e => { - const m = this._diffModel.get(); - if (!m) { return; } - const movedText = m.diff.get()!.movedTexts.find(m => m.lineRangeMapping.original.contains(e.position.lineNumber)); - m.syncedMovedTexts.set(movedText, undefined); - })); - this._register(this._editors.modified.onDidChangeCursorPosition(e => { - const m = this._diffModel.get(); - if (!m) { return; } - const movedText = m.diff.get()!.movedTexts.find(m => m.lineRangeMapping.modified.contains(e.position.lineNumber)); - m.syncedMovedTexts.set(movedText, undefined); - })); - // Revert change when an arrow is clicked. this._register(this._editors.modified.onMouseDown(event => { if (!event.event.rightButton && event.target.position && event.target.element?.className.includes('arrow-revert-change')) { @@ -518,6 +511,12 @@ export class DiffEditorWidget2 extends DelegatingEditor implements IDiffEditor { } destination.focus(); } + + exitCompareMove(): void { + const model = this._diffModel.get(); + if (!model) { return; } + model.movedTextToCompare.set(undefined, undefined); + } } function translatePosition(posInOriginal: Position, mappings: LineRangeMapping[]): Range { diff --git a/src/vs/editor/browser/widget/diffEditorWidget2/lineAlignment.ts b/src/vs/editor/browser/widget/diffEditorWidget2/lineAlignment.ts index 3a95ce28942..56357753f62 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget2/lineAlignment.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget2/lineAlignment.ts @@ -103,7 +103,7 @@ export class ViewZoneManager extends Disposable { const alignmentsSyncedMovedText = derived((reader) => { /** @description alignments */ - const syncedMovedText = this._diffModel.read(reader)?.syncedMovedTexts.read(reader); + const syncedMovedText = this._diffModel.read(reader)?.movedTextToCompare.read(reader); if (!syncedMovedText) { return null; } state.read(reader); const mappings = syncedMovedText.changes.map(c => new DiffMapping(c)); @@ -171,7 +171,7 @@ export class ViewZoneManager extends Disposable { const modLineHeight = this._editors.modified.getOption(EditorOption.lineHeight); - const syncedMovedText = this._diffModel.read(reader)?.syncedMovedTexts.read(reader); + const syncedMovedText = this._diffModel.read(reader)?.movedTextToCompare.read(reader); const mightContainNonBasicASCII = this._editors.original.getModel()?.mightContainNonBasicASCII() ?? false; const mightContainRTL = this._editors.original.getModel()?.mightContainRTL() ?? false; @@ -424,7 +424,7 @@ export class ViewZoneManager extends Disposable { this._register(autorun(reader => { /** @description update editor top offsets */ - const m = this._diffModel.read(reader)?.syncedMovedTexts.read(reader); + const m = this._diffModel.read(reader)?.movedTextToCompare.read(reader); let deltaOrigToMod = 0; if (m) { diff --git a/src/vs/editor/browser/widget/diffEditorWidget2/movedBlocksLines.ts b/src/vs/editor/browser/widget/diffEditorWidget2/movedBlocksLines.ts index 4453cb7ce2d..6a5316decba 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget2/movedBlocksLines.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget2/movedBlocksLines.ts @@ -3,15 +3,23 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { h } from 'vs/base/browser/dom'; +import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; +import { Action } from 'vs/base/common/actions'; import { booleanComparator, compareBy, findMaxIdxBy, numberComparator, tieBreakComparators } from 'vs/base/common/arrays'; +import { Codicon } from 'vs/base/common/codicons'; import { Disposable, toDisposable } from 'vs/base/common/lifecycle'; -import { IObservable, autorun, derived, keepAlive, observableFromEvent, observableSignalFromEvent, observableValue } from 'vs/base/common/observable'; +import { IObservable, autorun, autorunWithStore, constObservable, derived, derivedWithStore, keepAlive, observableFromEvent, observableSignalFromEvent, observableValue } from 'vs/base/common/observable'; +import { ThemeIcon } from 'vs/base/common/themables'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { DiffEditorEditors } from 'vs/editor/browser/widget/diffEditorWidget2/diffEditorEditors'; import { DiffEditorViewModel } from 'vs/editor/browser/widget/diffEditorWidget2/diffEditorViewModel'; +import { PlaceholderViewZone, ViewZoneOverlayWidget, applyStyle, applyViewZones } from 'vs/editor/browser/widget/diffEditorWidget2/utils'; import { EditorLayoutInfo } from 'vs/editor/common/config/editorOptions'; import { LineRange } from 'vs/editor/common/core/lineRange'; import { OffsetRange, OffsetRangeSet } from 'vs/editor/common/core/offsetRange'; +import { MovedText } from 'vs/editor/common/diff/linesDiffComputer'; +import { localize } from 'vs/nls'; export class MovedBlocksLinesPart extends Disposable { public static readonly movedCodeBlockPadding = 4; @@ -51,9 +59,50 @@ export class MovedBlocksLinesPart extends Disposable { })); this._register(keepAlive(this._state, true)); + + const movedBlockViewZones = derived(reader => { + const model = this._diffModel.read(reader); + const d = model?.diff.read(reader); + if (!d) { return []; } + return d.movedTexts.map(move => ({ + move, + original: new PlaceholderViewZone(constObservable(move.lineRangeMapping.original.startLineNumber - 1), 18), + modified: new PlaceholderViewZone(constObservable(move.lineRangeMapping.modified.startLineNumber - 1), 18), + })); + }); + + this._register(applyViewZones(this._editors.original, movedBlockViewZones.map(zones => zones.map(z => z.original)))); + this._register(applyViewZones(this._editors.modified, movedBlockViewZones.map(zones => zones.map(z => z.modified)))); + + this._register(autorunWithStore((reader, store) => { + const blocks = movedBlockViewZones.read(reader); + for (const b of blocks) { + store.add(new MovedBlockOverlayWidget(this._editors.original, b.original, b.move, 'original', this._diffModel.get()!)); + store.add(new MovedBlockOverlayWidget(this._editors.modified, b.modified, b.move, 'modified', this._diffModel.get()!)); + } + })); + + this._register(this._editors.original.onDidChangeCursorPosition(e => { + const m = this._diffModel.get(); + if (!m) { return; } + const movedText = m.diff.get()!.movedTexts.find(m => m.lineRangeMapping.original.contains(e.position.lineNumber)); + if (movedText !== m.movedTextToCompare.get()) { + m.movedTextToCompare.set(undefined, undefined); + } + m.setActiveMovedText(movedText); + })); + this._register(this._editors.modified.onDidChangeCursorPosition(e => { + const m = this._diffModel.get(); + if (!m) { return; } + const movedText = m.diff.get()!.movedTexts.find(m => m.lineRangeMapping.modified.contains(e.position.lineNumber)); + if (movedText !== m.movedTextToCompare.get()) { + m.movedTextToCompare.set(undefined, undefined); + } + m.setActiveMovedText(movedText); + })); } - private readonly _state = derived(reader => { + private readonly _state = derivedWithStore('state', (reader, store) => { /** @description update moved blocks lines */ this._element.replaceChildren(); @@ -125,21 +174,35 @@ export class MovedBlocksLinesPart extends Disposable { rect.setAttribute('height', `${rectHeight}`); this._element.appendChild(rect); + const g = document.createElementNS('http://www.w3.org/2000/svg', 'g'); + const path = document.createElementNS('http://www.w3.org/2000/svg', 'path'); - if (line.move === model.syncedMovedTexts.read(reader)) { - path.classList.add('currentMove'); - } + path.setAttribute('d', `M ${0} ${line.from} L ${verticalY} ${line.from} L ${verticalY} ${line.to} L ${right - arrowWidth} ${line.to}`); path.setAttribute('fill', 'none'); - this._element.appendChild(path); + g.appendChild(path); const arrowRight = document.createElementNS('http://www.w3.org/2000/svg', 'polygon'); arrowRight.classList.add('arrow'); - if (line.move === model.syncedMovedTexts.read(reader)) { - arrowRight.classList.add('currentMove'); - } + + store.add(autorun(reader => { + path.classList.toggle('currentMove', line.move === model.activeMovedText.read(reader)); + arrowRight.classList.toggle('currentMove', line.move === model.activeMovedText.read(reader)); + })); + arrowRight.setAttribute('points', `${right - arrowWidth},${line.to - arrowHeight / 2} ${right},${line.to} ${right - arrowWidth},${line.to + arrowHeight / 2}`); - this._element.appendChild(arrowRight); + g.appendChild(arrowRight); + + this._element.appendChild(g); + + /* + TODO@hediet + path.addEventListener('mouseenter', () => { + model.setHoveredMovedText(line.move); + }); + path.addEventListener('mouseleave', () => { + model.setHoveredMovedText(undefined); + });*/ idx++; } @@ -184,3 +247,84 @@ class LinesLayout { return this._trackCount; } } + +class MovedBlockOverlayWidget extends ViewZoneOverlayWidget { + private readonly _nodes = h('div.diff-moved-code-block', { style: { marginRight: '4px' } }, [ + h('div.text-content@textContent'), + h('div.action-bar@actionBar'), + ]); + + constructor( + private readonly _editor: ICodeEditor, + _viewZone: PlaceholderViewZone, + private readonly _move: MovedText, + private readonly _kind: 'original' | 'modified', + private readonly _diffModel: DiffEditorViewModel, + ) { + const root = h('div.diff-hidden-lines-widget'); + super(_editor, _viewZone, root.root); + root.root.appendChild(this._nodes.root); + + const editorLayout = observableFromEvent(this._editor.onDidLayoutChange, () => this._editor.getLayoutInfo()); + + this._register(applyStyle(this._nodes.root, { + paddingRight: editorLayout.map(l => l.verticalScrollbarWidth) + })); + + let text: string; + + if (_move.changes.length > 0) { + text = this._kind === 'original' ? localize( + 'codeMovedToWithChanges', + 'Code moved with changes to line {0}-{1}', + this._move.lineRangeMapping.modified.startLineNumber, + this._move.lineRangeMapping.modified.endLineNumberExclusive + ) : localize( + 'codeMovedFromWithChanges', + 'Code moved with changes from line {0}-{1}', + this._move.lineRangeMapping.original.startLineNumber, + this._move.lineRangeMapping.original.endLineNumberExclusive + ); + } else { + text = this._kind === 'original' ? localize( + 'codeMovedTo', + 'Code moved to line {0}-{1}', + this._move.lineRangeMapping.modified.startLineNumber, + this._move.lineRangeMapping.modified.endLineNumberExclusive + ) : localize( + 'codeMovedFrom', + 'Code moved from line {0}-{1}', + this._move.lineRangeMapping.original.startLineNumber, + this._move.lineRangeMapping.original.endLineNumberExclusive + ); + } + + const actionBar = this._register(new ActionBar(this._nodes.actionBar, { + highlightToggledItems: true, + })); + + const caption = new Action( + '', + text, + '', + false, + ); + actionBar.push(caption, { icon: false, label: true }); + + const actionCompare = new Action( + '', + 'Compare', + ThemeIcon.asClassName(Codicon.compareChanges), + true, + () => { + this._editor.focus(); + this._diffModel.movedTextToCompare.set(this._diffModel.movedTextToCompare.get() ? undefined : this._move, undefined); + }, + ); + this._register(autorun(reader => { + const isActive = this._diffModel.movedTextToCompare.read(reader) === _move; + actionCompare.checked = isActive; + })); + actionBar.push(actionCompare, { icon: true, label: false }); + } +} diff --git a/src/vs/editor/browser/widget/diffEditorWidget2/style.css b/src/vs/editor/browser/widget/diffEditorWidget2/style.css index 8fd6377362f..aa681f8f617 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget2/style.css +++ b/src/vs/editor/browser/widget/diffEditorWidget2/style.css @@ -86,6 +86,10 @@ stroke: var(--vscode-diffEditor-moveActive-border); } +.monaco-diff-editor .moved-blocks-lines path { + pointer-events: visiblestroke; +} + .monaco-diff-editor .moved-blocks-lines .arrow { fill: var(--vscode-diffEditor-move-border); } @@ -121,3 +125,15 @@ .monaco-editor .fold-unchanged { cursor: pointer; } + +.monaco-diff-editor .diff-moved-code-block { + display: flex; + justify-content: flex-end; + margin-top: -4px; +} + +.monaco-diff-editor .diff-moved-code-block .action-bar .action-label.codicon { + width: 12px; + height: 12px; + font-size: 12px; +} diff --git a/src/vs/editor/browser/widget/diffEditorWidget2/utils.ts b/src/vs/editor/browser/widget/diffEditorWidget2/utils.ts index 9a86bfd448b..8460b24326e 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget2/utils.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget2/utils.ts @@ -268,6 +268,8 @@ export interface CSSStyle { top: number | string; visibility: 'visible' | 'hidden' | 'collapse'; display: 'block' | 'inline' | 'inline-block' | 'flex' | 'none'; + paddingLeft: number | string; + paddingRight: number | string; } export function applyStyle(domNode: HTMLElement, style: Partial<{ [TKey in keyof CSSStyle]: CSSStyle[TKey] | IObservable | undefined }>) { @@ -280,6 +282,7 @@ export function applyStyle(domNode: HTMLElement, style: Partial<{ [TKey in keyof if (typeof val === 'number') { val = `${val}px`; } + key = key.replace(/[A-Z]/g, m => '-' + m.toLowerCase()); domNode.style[key as any] = val as any; } }); diff --git a/src/vs/editor/common/editorContextKeys.ts b/src/vs/editor/common/editorContextKeys.ts index c831d05fe21..a2b1a88cc44 100644 --- a/src/vs/editor/common/editorContextKeys.ts +++ b/src/vs/editor/common/editorContextKeys.ts @@ -27,6 +27,7 @@ export namespace EditorContextKeys { export const readOnly = new RawContextKey('editorReadonly', false, nls.localize('editorReadonly', "Whether the editor is read-only")); export const inDiffEditor = new RawContextKey('inDiffEditor', false, nls.localize('inDiffEditor', "Whether the context is a diff editor")); export const isEmbeddedDiffEditor = new RawContextKey('isEmbeddedDiffEditor', false, nls.localize('isEmbeddedDiffEditor', "Whether the context is an embedded diff editor")); + export const comparingMovedCode = new RawContextKey('comparingMovedCode', false, nls.localize('comparingMovedCode', "Whether a moved code block is selected for comparison")); export const accessibleDiffViewerVisible = new RawContextKey('accessibleDiffViewerVisible', false, nls.localize('accessibleDiffViewerVisible', "Whether the accessible diff viewer is visible")); export const diffEditorRenderSideBySideInlineBreakpointReached = new RawContextKey('diffEditorRenderSideBySideInlineBreakpointReached', false, nls.localize('diffEditorRenderSideBySideInlineBreakpointReached', "Whether the diff editor render side by side inline breakpoint is reached")); export const columnSelection = new RawContextKey('editorColumnSelection', false, nls.localize('editorColumnSelection', "Whether `editor.columnSelection` is enabled")); From 6225119b0ca825fd668780367894d9f6c6d8d9a6 Mon Sep 17 00:00:00 2001 From: Joyce Er Date: Wed, 23 Aug 2023 09:13:21 -0700 Subject: [PATCH 124/221] Show progress in chat placeholder content (#190782) * Show progress in chat placeholder content * Make property names consistent * Rename more properties * Address PR comments * Dispose of markdown render result * Look up `isPlaceholder` on `currentResponseData` --- .../contrib/chat/browser/chatListRenderer.ts | 28 ++++++++++++++++--- .../contrib/chat/browser/media/chat.css | 15 ++++++++++ .../contrib/chat/common/chatModel.ts | 21 ++++++++------ 3 files changed, 52 insertions(+), 12 deletions(-) diff --git a/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts b/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts index 52f971ad1b9..dad24e99b60 100644 --- a/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts +++ b/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts @@ -72,6 +72,7 @@ import { createFileIconThemableTreeContainerScope } from 'vs/workbench/contrib/f import { IFilesConfiguration } from 'vs/workbench/contrib/files/common/files'; import { IOpenerService } from 'vs/platform/opener/common/opener'; import { distinct } from 'vs/base/common/arrays'; +import { IPlaceholderMarkdownString } from 'vs/workbench/contrib/chat/common/chatModel'; const $ = dom.$; @@ -414,7 +415,7 @@ export class ChatListItemRenderer extends Disposable implements ITreeRenderer content.dispose() }; + } + private renderMarkdown(markdown: IMarkdownString, element: ChatTreeItem, disposables: DisposableStore, templateData: IChatListItemTemplate, fillInIncompleteTokens = false): IMarkdownRenderResult { const disposablesList: IDisposable[] = []; let codeBlockIndex = 0; @@ -622,7 +638,7 @@ export class ChatListItemRenderer extends Disposable implements ITreeRenderer): IWordCountResult | undefined { const rate = this.getProgressiveRenderRate(element); const numWordsToRender = renderData.lastRenderTime === 0 ? 1 : @@ -1189,3 +1205,7 @@ class ChatListTreeDataSource implements IAsyncDataSource; updateContent(responsePart: string | { treeData: IChatResponseProgressFileTreeData } | { placeholder: string; resolvedContent?: Promise }, quiet?: boolean): void; asString(): string; @@ -88,8 +88,11 @@ export class ChatRequestModel implements IChatRequestModel { } } +export interface IPlaceholderMarkdownString extends IMarkdownString { + isPlaceholder: boolean; +} -type ResponsePart = { string: IMarkdownString; resolving?: boolean } | { treeData: IChatResponseProgressFileTreeData; resolving?: boolean }; +type ResponsePart = { string: IMarkdownString; isPlaceholder?: boolean } | { treeData: IChatResponseProgressFileTreeData; isPlaceholder?: undefined }; export class Response implements IResponse { private _onDidChangeValue = new Emitter(); public get onDidChangeValue() { @@ -99,11 +102,11 @@ export class Response implements IResponse { // responseParts internally tracks all the response parts, including strings which are currently resolving, so that they can be updated when they do resolve private _responseParts: ResponsePart[]; // responseData externally presents the response parts with consolidated contiguous strings (including strings which were previously resolving) - private _responseData: (IMarkdownString | IChatResponseProgressFileTreeData)[]; + private _responseData: (IMarkdownString | IPlaceholderMarkdownString | IChatResponseProgressFileTreeData)[]; // responseRepr externally presents the response parts with consolidated contiguous strings (excluding tree data) private _responseRepr: string; - get value(): (IMarkdownString | IChatResponseProgressFileTreeData)[] { + get value(): (IMarkdownString | IPlaceholderMarkdownString | IChatResponseProgressFileTreeData)[] { return this._responseData; } @@ -127,7 +130,7 @@ export class Response implements IResponse { const responsePartLength = this._responseParts.length - 1; const lastResponsePart = this._responseParts[responsePartLength]; - if (lastResponsePart.resolving === true || isCompleteInteractiveProgressTreeData(lastResponsePart)) { + if (lastResponsePart.isPlaceholder === true || isCompleteInteractiveProgressTreeData(lastResponsePart)) { // The last part is resolving or a tree data item, start a new part this._responseParts.push({ string: new MarkdownString(responsePart) }); } else { @@ -138,16 +141,16 @@ export class Response implements IResponse { this._updateRepr(quiet); } else if ('placeholder' in responsePart) { // Add a new resolving part - const responsePosition = this._responseParts.push({ string: new MarkdownString(responsePart.placeholder), resolving: true }) - 1; + const responsePosition = this._responseParts.push({ string: new MarkdownString(responsePart.placeholder), isPlaceholder: true }) - 1; this._updateRepr(quiet); responsePart.resolvedContent?.then((content) => { // Replace the resolving part's content with the resolved response if (typeof content === 'string') { - this._responseParts[responsePosition] = { string: new MarkdownString(content), resolving: true }; + this._responseParts[responsePosition] = { string: new MarkdownString(content), isPlaceholder: true }; this._updateRepr(quiet); } else if (content.treeData) { - this._responseParts[responsePosition] = { treeData: content.treeData, resolving: true }; + this._responseParts[responsePosition] = { treeData: content.treeData }; this._updateRepr(quiet); } }); @@ -160,6 +163,8 @@ export class Response implements IResponse { this._responseData = this._responseParts.map(part => { if (isCompleteInteractiveProgressTreeData(part)) { return part.treeData; + } else if (part.isPlaceholder) { + return { ...part.string, isPlaceholder: true }; } return part.string; }); From 702a76bf5da92be1c91954c41b850f9c2f15d5a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mustafa=20Ate=C5=9F=20Uzun?= Date: Wed, 23 Aug 2023 19:16:16 +0300 Subject: [PATCH 125/221] fix: localize string typo (#191046) * fix: localize string typo * fix: suffix typo --- .../contrib/extensions/browser/extensionsViews.ts | 2 +- .../contrib/files/browser/views/explorerViewer.ts | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsViews.ts b/src/vs/workbench/contrib/extensions/browser/extensionsViews.ts index f8d7c21cea7..fc8215dff5b 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsViews.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsViews.ts @@ -1431,7 +1431,7 @@ export function getAriaLabelForExtension(extension: IExtension | null): string { if (!extension) { return ''; } - const publisher = extension.publisherDomain?.verified ? localize('extension.arialabel.verifiedPublihser', "Verified Publisher {0}", extension.publisherDisplayName) : localize('extension.arialabel.publihser', "Publisher {0}", extension.publisherDisplayName); + const publisher = extension.publisherDomain?.verified ? localize('extension.arialabel.verifiedPublisher', "Verified Publisher {0}", extension.publisherDisplayName) : localize('extension.arialabel.publisher', "Publisher {0}", extension.publisherDisplayName); const deprecated = extension?.deprecationInfo ? localize('extension.arialabel.deprecated', "Deprecated") : ''; const rating = extension?.rating ? localize('extension.arialabel.rating', "Rated {0} out of 5 stars by {1} users", extension.rating.toFixed(2), extension.ratingCount) : ''; return `${extension.displayName}, ${deprecated ? `${deprecated}, ` : ''}${extension.version}, ${publisher}, ${extension.description} ${rating ? `, ${rating}` : ''}`; diff --git a/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts b/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts index 6560e68e9a5..a25c052188a 100644 --- a/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts +++ b/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts @@ -1391,11 +1391,11 @@ export class FileDragAndDrop implements ITreeDragAndDrop { const resourceEdit = new ResourceFileEdit(resource, newResource, { copy: true, overwrite: allowOverwrite }); resourceFileEdits.push(resourceEdit); } - const labelSufix = getFileOrFolderLabelSufix(sources); + const labelSuffix = getFileOrFolderLabelSuffix(sources); await this.explorerService.applyBulkEdit(resourceFileEdits, { confirmBeforeUndo: explorerConfig.confirmUndo === UndoConfirmLevel.Default || explorerConfig.confirmUndo === UndoConfirmLevel.Verbose, - undoLabel: localize('copy', "Copy {0}", labelSufix), - progressLabel: localize('copying', "Copying {0}", labelSufix), + undoLabel: localize('copy', "Copy {0}", labelSuffix), + progressLabel: localize('copying', "Copying {0}", labelSuffix), }); const editors = resourceFileEdits.filter(edit => { @@ -1410,11 +1410,11 @@ export class FileDragAndDrop implements ITreeDragAndDrop { // Do not allow moving readonly items const resourceFileEdits = sources.filter(source => !source.isReadonly).map(source => new ResourceFileEdit(source.resource, joinPath(target.resource, source.name))); - const labelSufix = getFileOrFolderLabelSufix(sources); + const labelSuffix = getFileOrFolderLabelSuffix(sources); const options = { confirmBeforeUndo: this.configurationService.getValue().explorer.confirmUndo === UndoConfirmLevel.Verbose, - undoLabel: localize('move', "Move {0}", labelSufix), - progressLabel: localize('moving', "Moving {0}", labelSufix) + undoLabel: localize('move', "Move {0}", labelSuffix), + progressLabel: localize('moving', "Moving {0}", labelSuffix) }; try { @@ -1518,7 +1518,7 @@ export class ExplorerCompressionDelegate implements ITreeCompressionDelegate Date: Wed, 23 Aug 2023 10:18:57 -0700 Subject: [PATCH 126/221] =?UTF-8?q?Broken=20`search.action.replace`=20defa?= =?UTF-8?q?ult=20mac=20shortcut=20(`=E2=87=A7`+`=E2=8C=98`+`1`)=20(#191102?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #189866 --- src/vs/workbench/contrib/search/browser/searchView.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/search/browser/searchView.ts b/src/vs/workbench/contrib/search/browser/searchView.ts index d6be8a28998..07576765667 100644 --- a/src/vs/workbench/contrib/search/browser/searchView.ts +++ b/src/vs/workbench/contrib/search/browser/searchView.ts @@ -903,8 +903,8 @@ export class SearchView extends ViewPane { } let editable = false; - if (focus instanceof MatchInNotebook) { - editable = !focus.isWebviewMatch(); + if (focus instanceof Match) { + editable = (focus instanceof MatchInNotebook) ? !focus.isWebviewMatch() : true; } else if (focus instanceof FileMatch) { editable = !focus.hasOnlyReadOnlyMatches(); } else if (focus instanceof FolderMatch) { From bd67b50dfdf98e56bd79790ab7e2bc5a292ccdb4 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Wed, 23 Aug 2023 19:28:19 +0200 Subject: [PATCH 127/221] Remove tree item checkbox proposal from tests (#191084) Fixes #191081 --- extensions/vscode-api-tests/package.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/extensions/vscode-api-tests/package.json b/extensions/vscode-api-tests/package.json index 9d50e393547..a28d4f806aa 100644 --- a/extensions/vscode-api-tests/package.json +++ b/extensions/vscode-api-tests/package.json @@ -45,8 +45,7 @@ "textSearchProvider", "timeline", "tokenInformation", - "treeItemCheckbox", - "treeViewActiveItem", + "treeViewActiveItem", "treeViewReveal", "workspaceTrust", "telemetry", From 01857efa503aeed4efeada51aded87d742399dee Mon Sep 17 00:00:00 2001 From: meganrogge Date: Wed, 23 Aug 2023 10:29:59 -0700 Subject: [PATCH 128/221] allow different keybindings --- .../contrib/terminal/common/terminal.ts | 1 + .../terminal/common/terminalContextKey.ts | 4 +++ .../terminal/common/terminalStrings.ts | 4 +++ .../terminal.accessibility.contribution.ts | 32 +++++++++++++++++-- .../browser/terminalAccessibleBuffer.ts | 2 +- .../browser/terminalAccessibleWidget.ts | 19 +++++++++-- 6 files changed, 56 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/common/terminal.ts b/src/vs/workbench/contrib/terminal/common/terminal.ts index 77e37c5b574..6402859667a 100644 --- a/src/vs/workbench/contrib/terminal/common/terminal.ts +++ b/src/vs/workbench/contrib/terminal/common/terminal.ts @@ -495,6 +495,7 @@ export const enum TerminalCommandId { HideSuggestWidget = 'workbench.action.terminal.hideSuggestWidget', FocusHover = 'workbench.action.terminal.focusHover', ShowEnvironmentContributions = 'workbench.action.terminal.showEnvironmentContributions', + FocusAndHideAccessibleBuffer = 'workbench.action.terminal.focusAndHideAccessibleBuffer', // Developer commands diff --git a/src/vs/workbench/contrib/terminal/common/terminalContextKey.ts b/src/vs/workbench/contrib/terminal/common/terminalContextKey.ts index 1d480dbd649..ce4f7a4168c 100644 --- a/src/vs/workbench/contrib/terminal/common/terminalContextKey.ts +++ b/src/vs/workbench/contrib/terminal/common/terminalContextKey.ts @@ -16,6 +16,7 @@ export const enum TerminalContextKeyStrings { Focus = 'terminalFocus', FocusInAny = 'terminalFocusInAny', AccessibleBufferFocus = 'terminalAccessibleBufferFocus', + AccessibleBufferOnLastLine = 'terminalAccessibleBufferOnLastLine', EditorFocus = 'terminalEditorFocus', TabsFocus = 'terminalTabsFocus', WebExtensionContributedProfile = 'terminalWebExtensionContributedProfile', @@ -51,6 +52,9 @@ export namespace TerminalContextKeys { /** Whether the accessible buffer is focused. */ export const accessibleBufferFocus = new RawContextKey(TerminalContextKeyStrings.AccessibleBufferFocus, false, localize('terminalAccessibleBufferFocusContextKey', "Whether the terminal accessible buffer is focused.")); + /** Whether the accessible buffer focus is on the last line. */ + export const accessibleBufferOnLastLine = new RawContextKey(TerminalContextKeyStrings.AccessibleBufferOnLastLine, false, localize('terminalAccessibleBufferOnLastLineContextKey', "Whether the accessible buffer focus is on the last line.")); + /** Whether a terminal in the editor area is focused. */ export const editorFocus = new RawContextKey(TerminalContextKeyStrings.EditorFocus, false, localize('terminalEditorFocusContextKey', "Whether a terminal in the editor area is focused.")); diff --git a/src/vs/workbench/contrib/terminal/common/terminalStrings.ts b/src/vs/workbench/contrib/terminal/common/terminalStrings.ts index 75e281c9f2d..43b4589df6c 100644 --- a/src/vs/workbench/contrib/terminal/common/terminalStrings.ts +++ b/src/vs/workbench/contrib/terminal/common/terminalStrings.ts @@ -22,6 +22,10 @@ export const terminalStrings = { value: localize('workbench.action.terminal.focus', "Focus Terminal"), original: 'Focus Terminal' }, + focusAndHideAccessibleBuffer: { + value: localize('workbench.action.terminal.focusAndHideAccessibleBuffer', "Focus Terminal and Hide Accessible Buffer"), + original: 'Focus Terminal and Hide Accessible Buffer' + }, kill: { value: localize('killTerminal', "Kill Terminal"), original: 'Kill Terminal', diff --git a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminal.accessibility.contribution.ts b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminal.accessibility.contribution.ts index b69943c18de..6fe33fdff35 100644 --- a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminal.accessibility.contribution.ts +++ b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminal.accessibility.contribution.ts @@ -11,7 +11,7 @@ import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { IQuickPick, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput'; -import { terminalTabFocusModeContextKey } from 'vs/platform/terminal/common/terminal'; +import { TerminalLocation, terminalTabFocusModeContextKey } from 'vs/platform/terminal/common/terminal'; import { IAccessibleViewService } from 'vs/workbench/contrib/accessibility/browser/accessibleView'; import { AccessibilityHelpAction } from 'vs/workbench/contrib/accessibility/browser/accessibleViewActions'; import { ITerminalContribution, ITerminalInstance, ITerminalService, IXtermTerminal } from 'vs/workbench/contrib/terminal/browser/terminal'; @@ -20,6 +20,7 @@ import { registerTerminalContribution } from 'vs/workbench/contrib/terminal/brow import { TerminalWidgetManager } from 'vs/workbench/contrib/terminal/browser/widgets/widgetManager'; import { ITerminalProcessManager, TerminalCommandId } from 'vs/workbench/contrib/terminal/common/terminal'; import { TerminalContextKeys } from 'vs/workbench/contrib/terminal/common/terminalContextKey'; +import { terminalStrings } from 'vs/workbench/contrib/terminal/common/terminalStrings'; import { TerminalAccessibleContentProvider } from 'vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibilityHelp'; import { AccessibleBufferWidget, NavigationType } from 'vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer'; import { TextAreaSyncAddon } from 'vs/workbench/contrib/terminalContrib/accessibility/browser/textAreaSyncAddon'; @@ -47,7 +48,7 @@ class TextAreaSyncContribution extends DisposableStore implements ITerminalContr } registerTerminalContribution(TextAreaSyncContribution.ID, TextAreaSyncContribution); -class AccessibleBufferContribution extends DisposableStore implements ITerminalContribution { +export class AccessibleBufferContribution extends DisposableStore implements ITerminalContribution { static readonly ID = 'terminal.accessible-buffer'; private _xterm: IXtermTerminal & { raw: Terminal } | undefined; static get(instance: ITerminalInstance): AccessibleBufferContribution | null { @@ -83,6 +84,9 @@ class AccessibleBufferContribution extends DisposableStore implements ITerminalC navigateToCommand(type: NavigationType): void { return this._accessibleBufferWidget?.navigateToCommand(type); } + hide(): void { + this._accessibleBufferWidget?.hide(); + } } registerTerminalContribution(AccessibleBufferContribution.ID, AccessibleBufferContribution); @@ -114,6 +118,7 @@ registerTerminalAction({ keybinding: [ { primary: KeyMod.Shift | KeyCode.Tab, + secondary: [KeyMod.CtrlCmd | KeyCode.UpArrow, KeyMod.Alt | KeyCode.F2], weight: KeybindingWeight.WorkbenchContrib, when: ContextKeyExpr.and(CONTEXT_ACCESSIBILITY_MODE_ENABLED, TerminalContextKeys.focus, ContextKeyExpr.or(terminalTabFocusModeContextKey, TerminalContextKeys.accessibleBufferFocus.negate())) } @@ -204,3 +209,26 @@ registerTerminalAction({ await AccessibleBufferContribution.get(instance)?.navigateToCommand(NavigationType.Previous); } }); + +registerTerminalAction({ + id: TerminalCommandId.FocusAndHideAccessibleBuffer, + title: terminalStrings.focusAndHideAccessibleBuffer, + f1: false, + keybinding: { + when: ContextKeyExpr.and(TerminalContextKeys.accessibleBufferFocus, TerminalContextKeys.accessibleBufferOnLastLine), + primary: KeyMod.CtrlCmd | KeyCode.DownArrow, + weight: KeybindingWeight.WorkbenchContrib + }, + precondition: ContextKeyExpr.or(TerminalContextKeys.processSupported, TerminalContextKeys.terminalHasBeenCreated), + run: async (c) => { + const instance = c.service.activeInstance || await c.service.createTerminal({ location: TerminalLocation.Panel }); + if (!instance) { + return; + } + const contribution = instance.getContribution('terminal.accessible-buffer'); + if (contribution) { + contribution.hide(); + } + instance.focus(true); + } +}); diff --git a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts index fab258f94e6..bca9d64d23a 100644 --- a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts +++ b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts @@ -56,7 +56,7 @@ export class AccessibleBufferWidget extends TerminalAccessibleWidget { @ITerminalLogService private readonly _logService: ITerminalLogService, @ITerminalService _terminalService: ITerminalService ) { - super(ClassName.AccessibleBuffer, _instance, _xterm, TerminalContextKeys.accessibleBufferFocus, _instantiationService, _modelService, _configurationService, _contextKeyService, _terminalService); + super(ClassName.AccessibleBuffer, _instance, _xterm, TerminalContextKeys.accessibleBufferFocus, TerminalContextKeys.accessibleBufferOnLastLine, _instantiationService, _modelService, _configurationService, _contextKeyService, _terminalService); this._bufferTracker = _instantiationService.createInstance(BufferContentTracker, _xterm); this.element.ariaRoleDescription = localize('terminal.integrated.accessibleBuffer', 'Terminal buffer'); this.updateEditor(); diff --git a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleWidget.ts b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleWidget.ts index 46a475b67f3..77fd6173934 100644 --- a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleWidget.ts +++ b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleWidget.ts @@ -41,6 +41,7 @@ export abstract class TerminalAccessibleWidget extends DisposableStore { protected _listeners: IDisposable[] = []; private readonly _focusedContextKey?: IContextKey; + private readonly _focusedLastLineContextKey?: IContextKey; private readonly _focusTracker?: dom.IFocusTracker; constructor( @@ -48,6 +49,7 @@ export abstract class TerminalAccessibleWidget extends DisposableStore { protected readonly _instance: Pick, protected readonly _xterm: Pick & { raw: Terminal }, private _focusContextKey: RawContextKey | undefined, + private _focusLastLineContextKey: RawContextKey | undefined, @IInstantiationService private readonly _instantiationService: IInstantiationService, @IModelService private readonly _modelService: IModelService, @IConfigurationService private readonly _configurationService: IConfigurationService, @@ -87,11 +89,22 @@ export abstract class TerminalAccessibleWidget extends DisposableStore { this._element.replaceChildren(this._editorContainer); this._xtermElement.insertAdjacentElement('beforebegin', this._element); - if (this._focusContextKey) { + if (this._focusContextKey && this._focusLastLineContextKey) { this._focusTracker = this.add(dom.trackFocus(this._editorContainer)); this._focusedContextKey = this._focusContextKey.bindTo(this._contextKeyService); - this.add(this._focusTracker.onDidFocus(() => this._focusedContextKey?.set(true))); - this.add(this._focusTracker.onDidBlur(() => this._focusedContextKey?.reset())); + this._focusedLastLineContextKey = this._focusLastLineContextKey.bindTo(this._contextKeyService); + this.add(this._focusTracker.onDidFocus(() => { + this._focusedContextKey?.set(true); + this._focusedLastLineContextKey?.set(this._editorWidget.getSelection()?.positionLineNumber === this._editorWidget.getModel()?.getLineCount()); + })); + this.add(this._focusTracker.onDidBlur(() => { + this._focusedContextKey?.reset(); + this._focusedLastLineContextKey?.reset(); + })); + this._editorWidget.onDidChangeCursorPosition(() => { + console.log(this._editorWidget.getSelection()?.positionLineNumber === this._editorWidget.getModel()?.getLineCount()); + this._focusedLastLineContextKey?.set(this._editorWidget.getSelection()?.positionLineNumber === this._editorWidget.getModel()?.getLineCount()); + }); } this.add(Event.runAndSubscribe(this._xterm.raw.onResize, () => this.layout())); From 30907cfef18c34f8d799910712a6194bae8b9a48 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Wed, 23 Aug 2023 19:31:51 +0200 Subject: [PATCH 129/221] TreeItem.label ignored by resourceUri for untitled editor (#191103) Fixes #189505 --- src/vs/workbench/browser/parts/views/treeView.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/browser/parts/views/treeView.ts b/src/vs/workbench/browser/parts/views/treeView.ts index aedd476a89d..c5dc8bf57e3 100644 --- a/src/vs/workbench/browser/parts/views/treeView.ts +++ b/src/vs/workbench/browser/parts/views/treeView.ts @@ -1217,7 +1217,8 @@ class TreeRenderer extends Disposable implements ITreeRenderer Date: Wed, 23 Aug 2023 10:32:56 -0700 Subject: [PATCH 130/221] fix #189358 --- .../browser/terminal.accessibility.contribution.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminal.accessibility.contribution.ts b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminal.accessibility.contribution.ts index 6fe33fdff35..61d6cc20f6b 100644 --- a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminal.accessibility.contribution.ts +++ b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminal.accessibility.contribution.ts @@ -166,8 +166,7 @@ registerTerminalAction({ weight: KeybindingWeight.WorkbenchContrib + 2 }, { - primary: KeyMod.CtrlCmd | KeyCode.DownArrow, - mac: { primary: KeyMod.Alt | KeyCode.DownArrow }, + primary: KeyMod.Alt | KeyCode.DownArrow, when: ContextKeyExpr.and(TerminalContextKeys.accessibleBufferFocus, CONTEXT_ACCESSIBILITY_MODE_ENABLED), weight: KeybindingWeight.WorkbenchContrib + 2 } From cbc3479604b22f3c573932a46766d43563bb2f06 Mon Sep 17 00:00:00 2001 From: meganrogge Date: Wed, 23 Aug 2023 10:41:27 -0700 Subject: [PATCH 131/221] Revert "Merge pull request #190776 from microsoft/merogge/delay" This reverts commit 990da210e0e4fc528570ab83d068259766ff4e49, reversing changes made to 1f76cf794b240be23d6135831ed41b160991804f. --- .../accessibility/browser/accessibilityContributions.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/contrib/accessibility/browser/accessibilityContributions.ts b/src/vs/workbench/contrib/accessibility/browser/accessibilityContributions.ts index 80cdebaab8e..3d6968b88c4 100644 --- a/src/vs/workbench/contrib/accessibility/browser/accessibilityContributions.ts +++ b/src/vs/workbench/contrib/accessibility/browser/accessibilityContributions.ts @@ -282,7 +282,6 @@ export class InlineCompletionsAccessibleViewContribution extends Disposable { this._register(AccessibleViewAction.addImplementation(95, 'inline-completions', accessor => { const accessibleViewService = accessor.get(IAccessibleViewService); const codeEditorService = accessor.get(ICodeEditorService); - const contextViewService = accessor.get(IContextViewService); const show = () => { const editor = codeEditorService.getActiveCodeEditor() || codeEditorService.getFocusedCodeEditor(); if (!editor) { @@ -311,12 +310,10 @@ export class InlineCompletionsAccessibleViewContribution extends Disposable { editor.focus(); }, next() { - contextViewService.hideContextView(); - setTimeout(() => model.next().then(() => show()), 50); + model.next().then(() => show()); }, previous() { - contextViewService.hideContextView(); - setTimeout(() => model.previous().then(() => show()), 50); + model.previous().then(() => show()); }, options: this._options }); From 2ab4a3f547d378d5df7530922bd001376e714795 Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Wed, 23 Aug 2023 10:41:33 -0700 Subject: [PATCH 132/221] tunnels: implement default port forwarding for managed RA's (#191099) * tunnels: implement default port forwarding for managed RA's The default implementation of port forwarding works from the shared process to traditional addressed remote authorities. However, this didn't work with managed remote authorities. Rather than implementing a chain of message passing from the shared process back up to the extension host, this PR reuses the `NodeRemoteTunnel` to provide default forwarding logic in the Node ext host. It also makes the `ManagedSocket` more generic for reuse there. Fixes #190859 * fix * address comments * address comments, fix build * rm import --- .../platform/remote/common/managedSocket.ts | 119 ++++++++++++++++++ src/vs/platform/tunnel/node/tunnelService.ts | 50 +++++--- .../api/browser/mainThreadManagedSockets.ts | 118 +++-------------- .../api/common/extHostExtensionService.ts | 6 +- .../api/common/extHostTunnelService.ts | 21 +++- .../api/node/extHost.node.services.ts | 3 + .../api/node/extHostTunnelService.ts | 112 ++++++++++++++++- .../browser/mainThreadManagedSockets.test.ts | 7 +- 8 files changed, 311 insertions(+), 125 deletions(-) diff --git a/src/vs/platform/remote/common/managedSocket.ts b/src/vs/platform/remote/common/managedSocket.ts index 9cbf5f326e8..0f55617264d 100644 --- a/src/vs/platform/remote/common/managedSocket.ts +++ b/src/vs/platform/remote/common/managedSocket.ts @@ -4,6 +4,9 @@ *--------------------------------------------------------------------------------------------*/ import { VSBuffer, encodeBase64 } from 'vs/base/common/buffer'; +import { Emitter, Event, PauseableEmitter } from 'vs/base/common/event'; +import { Disposable, DisposableStore } from 'vs/base/common/lifecycle'; +import { ISocket, SocketCloseEvent, SocketDiagnostics, SocketDiagnosticsEventType } from 'vs/base/parts/ipc/common/ipc.net'; export const makeRawSocketHeaders = (path: string, query: string, deubgLabel: string) => { // https://tools.ietf.org/html/rfc6455#section-4 @@ -24,3 +27,119 @@ export const makeRawSocketHeaders = (path: string, query: string, deubgLabel: st }; export const socketRawEndHeaderSequence = VSBuffer.fromString('\r\n\r\n'); + +export interface RemoteSocketHalf { + onData: Emitter; + onClose: Emitter; + onEnd: Emitter; +} + +/** Should be called immediately after making a ManagedSocket to make it ready for data flow. */ +export async function connectManagedSocket( + socket: T, + path: string, query: string, debugLabel: string, + half: RemoteSocketHalf +): Promise { + socket.write(VSBuffer.fromString(makeRawSocketHeaders(path, query, debugLabel))); + + const d = new DisposableStore(); + try { + return await new Promise((resolve, reject) => { + let dataSoFar: VSBuffer | undefined; + d.add(socket.onData(d_1 => { + if (!dataSoFar) { + dataSoFar = d_1; + } else { + dataSoFar = VSBuffer.concat([dataSoFar, d_1], dataSoFar.byteLength + d_1.byteLength); + } + + const index = dataSoFar.indexOf(socketRawEndHeaderSequence); + if (index === -1) { + return; + } + + resolve(socket); + // pause data events until the socket consumer is hooked up. We may + // immediately emit remaining data, but if not there may still be + // microtasks queued which would fire data into the abyss. + socket.pauseData(); + + const rest = dataSoFar.slice(index + socketRawEndHeaderSequence.byteLength); + if (rest.byteLength) { + half.onData.fire(rest); + } + })); + + d.add(socket.onClose(err => reject(err ?? new Error('socket closed')))); + d.add(socket.onEnd(() => reject(new Error('socket ended')))); + }); + } catch (e) { + socket.dispose(); + throw e; + } finally { + d.dispose(); + } +} + +export abstract class ManagedSocket extends Disposable implements ISocket { + private readonly pausableDataEmitter = this._register(new PauseableEmitter()); + + public onData: Event = (...args) => { + if (this.pausableDataEmitter.isPaused) { + queueMicrotask(() => this.pausableDataEmitter.resume()); + } + return this.pausableDataEmitter.event(...args); + }; + public onClose: Event; + public onEnd: Event; + + private readonly didDisposeEmitter = this._register(new Emitter()); + public onDidDispose = this.didDisposeEmitter.event; + + private ended = false; + + protected constructor( + private readonly debugLabel: string, + half: RemoteSocketHalf, + ) { + super(); + + this._register(half.onData); + this._register(half.onData.event(data => this.pausableDataEmitter.fire(data))); + + this.onClose = this._register(half.onClose).event; + this.onEnd = this._register(half.onEnd).event; + } + + /** Pauses data events until a new listener comes in onData() */ + public pauseData() { + this.pausableDataEmitter.pause(); + } + + /** Flushes data to the socket. */ + public drain(): Promise { + return Promise.resolve(); + } + + /** Ends the remote socket. */ + public end(): void { + this.ended = true; + this.closeRemote(); + } + + public abstract write(buffer: VSBuffer): void; + protected abstract closeRemote(): void; + + traceSocketEvent(type: SocketDiagnosticsEventType, data?: any): void { + SocketDiagnostics.traceSocketEvent(this, this.debugLabel, type, data); + } + + override dispose(): void { + if (!this.ended) { + this.closeRemote(); + } + + this.didDisposeEmitter.fire(); + super.dispose(); + } +} diff --git a/src/vs/platform/tunnel/node/tunnelService.ts b/src/vs/platform/tunnel/node/tunnelService.ts index 50eb82abc61..0894400360d 100644 --- a/src/vs/platform/tunnel/node/tunnelService.ts +++ b/src/vs/platform/tunnel/node/tunnelService.ts @@ -10,14 +10,15 @@ import { NodeSocket } from 'vs/base/parts/ipc/node/ipc.net'; import { Barrier } from 'vs/base/common/async'; import { Disposable } from 'vs/base/common/lifecycle'; +import { OS } from 'vs/base/common/platform'; +import { ISocket } from 'vs/base/parts/ipc/common/ipc.net'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ILogService } from 'vs/platform/log/common/log'; import { IProductService } from 'vs/platform/product/common/productService'; -import { connectRemoteAgentTunnel, IAddressProvider, IConnectionOptions } from 'vs/platform/remote/common/remoteAgentConnection'; -import { AbstractTunnelService, isAllInterfaces, ISharedTunnelsService as ISharedTunnelsService, isLocalhost, isPortPrivileged, isTunnelProvider, ITunnelProvider, ITunnelService, RemoteTunnel, TunnelPrivacyId } from 'vs/platform/tunnel/common/tunnel'; -import { ISignService } from 'vs/platform/sign/common/sign'; -import { OS } from 'vs/base/common/platform'; +import { IAddressProvider, IConnectionOptions, connectRemoteAgentTunnel } from 'vs/platform/remote/common/remoteAgentConnection'; import { IRemoteSocketFactoryService } from 'vs/platform/remote/common/remoteSocketFactoryService'; +import { ISignService } from 'vs/platform/sign/common/sign'; +import { AbstractTunnelService, ISharedTunnelsService, ITunnelProvider, ITunnelService, RemoteTunnel, TunnelPrivacyId, isAllInterfaces, isLocalhost, isPortPrivileged, isTunnelProvider } from 'vs/platform/tunnel/common/tunnel'; async function createRemoteTunnel(options: IConnectionOptions, defaultTunnelHost: string, tunnelRemoteHost: string, tunnelRemotePort: number, tunnelLocalPort?: number): Promise { let readyTunnel: NodeRemoteTunnel | undefined; @@ -32,7 +33,7 @@ async function createRemoteTunnel(options: IConnectionOptions, defaultTunnelHost return readyTunnel!; } -class NodeRemoteTunnel extends Disposable implements RemoteTunnel { +export class NodeRemoteTunnel extends Disposable implements RemoteTunnel { public readonly tunnelRemotePort: number; public tunnelLocalPort!: number; @@ -113,7 +114,7 @@ class NodeRemoteTunnel extends Disposable implements RemoteTunnel { const tunnelRemoteHost = (isLocalhost(this.tunnelRemoteHost) || isAllInterfaces(this.tunnelRemoteHost)) ? 'localhost' : this.tunnelRemoteHost; const protocol = await connectRemoteAgentTunnel(this._options, tunnelRemoteHost, this.tunnelRemotePort); - const remoteSocket = (protocol.getSocket()).socket; + const remoteSocket = protocol.getSocket(); const dataChunk = protocol.readEntireBuffer(); protocol.dispose(); @@ -132,17 +133,19 @@ class NodeRemoteTunnel extends Disposable implements RemoteTunnel { if (localSocket.localAddress) { this._socketsDispose.delete(localSocket.localAddress); } - remoteSocket.destroy(); + if (remoteSocket instanceof NodeSocket) { + remoteSocket.socket.destroy(); + } else { + remoteSocket.end(); + } }); - remoteSocket.on('end', () => localSocket.end()); - remoteSocket.on('close', () => localSocket.end()); - remoteSocket.on('error', () => { - localSocket.destroy(); - }); + if (remoteSocket instanceof NodeSocket) { + this._mirrorNodeSocket(localSocket, remoteSocket); + } else { + this._mirrorGenericSocket(localSocket, remoteSocket); + } - localSocket.pipe(remoteSocket); - remoteSocket.pipe(localSocket); if (localSocket.localAddress) { this._socketsDispose.set(localSocket.localAddress, () => { // Need to end instead of unpipe, otherwise whatever is connected locally could end up "stuck" with whatever state it had until manually exited. @@ -151,6 +154,25 @@ class NodeRemoteTunnel extends Disposable implements RemoteTunnel { }); } } + + private _mirrorGenericSocket(localSocket: net.Socket, remoteSocket: ISocket) { + remoteSocket.onClose(() => localSocket.destroy()); + remoteSocket.onEnd(() => localSocket.end()); + remoteSocket.onData(d => localSocket.write(d.buffer)); + localSocket.resume(); + } + + private _mirrorNodeSocket(localSocket: net.Socket, remoteNodeSocket: NodeSocket) { + const remoteSocket = remoteNodeSocket.socket; + remoteSocket.on('end', () => localSocket.end()); + remoteSocket.on('close', () => localSocket.end()); + remoteSocket.on('error', () => { + localSocket.destroy(); + }); + + remoteSocket.pipe(localSocket); + localSocket.pipe(remoteSocket); + } } export class BaseTunnelService extends AbstractTunnelService { diff --git a/src/vs/workbench/api/browser/mainThreadManagedSockets.ts b/src/vs/workbench/api/browser/mainThreadManagedSockets.ts index dbd5c34ac3e..5cae557028c 100644 --- a/src/vs/workbench/api/browser/mainThreadManagedSockets.ts +++ b/src/vs/workbench/api/browser/mainThreadManagedSockets.ts @@ -3,15 +3,15 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { MainContext, ExtHostContext, MainThreadManagedSocketsShape, ExtHostManagedSocketsShape } from 'vs/workbench/api/common/extHost.protocol'; -import { extHostNamedCustomer, IExtHostContext } from 'vs/workbench/services/extensions/common/extHostCustomers'; -import { Disposable, DisposableStore, IDisposable } from 'vs/base/common/lifecycle'; -import { ManagedRemoteConnection, RemoteConnectionType } from 'vs/platform/remote/common/remoteAuthorityResolver'; import { VSBuffer } from 'vs/base/common/buffer'; +import { Emitter } from 'vs/base/common/event'; +import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; +import { ISocket, SocketCloseEventType } from 'vs/base/parts/ipc/common/ipc.net'; +import { ManagedSocket, RemoteSocketHalf, connectManagedSocket } from 'vs/platform/remote/common/managedSocket'; +import { ManagedRemoteConnection, RemoteConnectionType } from 'vs/platform/remote/common/remoteAuthorityResolver'; import { IRemoteSocketFactoryService, ISocketFactory } from 'vs/platform/remote/common/remoteSocketFactoryService'; -import { ISocket, SocketCloseEvent, SocketCloseEventType, SocketDiagnostics, SocketDiagnosticsEventType } from 'vs/base/parts/ipc/common/ipc.net'; -import { Emitter, Event, PauseableEmitter } from 'vs/base/common/event'; -import { makeRawSocketHeaders, socketRawEndHeaderSequence } from 'vs/platform/remote/common/managedSocket'; +import { ExtHostContext, ExtHostManagedSocketsShape, MainContext, MainThreadManagedSocketsShape } from 'vs/workbench/api/common/extHost.protocol'; +import { IExtHostContext, extHostNamedCustomer } from 'vs/workbench/services/extensions/common/extHostCustomers'; @extHostNamedCustomer(MainContext.MainThreadManagedSockets) export class MainThreadManagedSockets extends Disposable implements MainThreadManagedSocketsShape { @@ -51,7 +51,7 @@ export class MainThreadManagedSockets extends Disposable implements MainThreadMa }; that._remoteSockets.set(socketId, half); - ManagedSocket.connect(socketId, that._proxy, path, query, debugLabel, half) + MainThreadManagedSocket.connect(socketId, that._proxy, path, query, debugLabel, half) .then( socket => { socket.onDidDispose(() => that._remoteSockets.delete(socketId)); @@ -91,117 +91,35 @@ export class MainThreadManagedSockets extends Disposable implements MainThreadMa } } -export interface RemoteSocketHalf { - onData: Emitter; - onClose: Emitter; - onEnd: Emitter; -} - -export class ManagedSocket extends Disposable implements ISocket { +export class MainThreadManagedSocket extends ManagedSocket { public static connect( socketId: number, proxy: ExtHostManagedSocketsShape, path: string, query: string, debugLabel: string, - half: RemoteSocketHalf - ): Promise { - const socket = new ManagedSocket(socketId, proxy, debugLabel, half.onClose, half.onData, half.onEnd); - - socket.write(VSBuffer.fromString(makeRawSocketHeaders(path, query, debugLabel))); - - const d = new DisposableStore(); - return new Promise((resolve, reject) => { - let dataSoFar: VSBuffer | undefined; - d.add(socket.onData(d => { - if (!dataSoFar) { - dataSoFar = d; - } else { - dataSoFar = VSBuffer.concat([dataSoFar, d], dataSoFar.byteLength + d.byteLength); - } - - const index = dataSoFar.indexOf(socketRawEndHeaderSequence); - if (index === -1) { - return; - } - - resolve(socket); - // pause data events until the socket consumer is hooked up. We may - // immediately emit remaining data, but if not there may still be - // microtasks queued which would fire data into the abyss. - socket.pauseData(); - - const rest = dataSoFar.slice(index + socketRawEndHeaderSequence.byteLength); - if (rest.byteLength) { - half.onData.fire(rest); - } - })); - - d.add(socket.onClose(err => reject(err ?? new Error('socket closed')))); - d.add(socket.onEnd(() => reject(new Error('socket ended')))); - }).finally(() => d.dispose()); + ): Promise { + const socket = new MainThreadManagedSocket(socketId, proxy, debugLabel, half); + return connectManagedSocket(socket, path, query, debugLabel, half); } - private readonly pausableDataEmitter = this._register(new PauseableEmitter()); - - public onData: Event = (...args) => { - if (this.pausableDataEmitter.isPaused) { - queueMicrotask(() => this.pausableDataEmitter.resume()); - } - return this.pausableDataEmitter.event(...args); - }; - public onClose: Event; - public onEnd: Event; - - private readonly didDisposeEmitter = this._register(new Emitter()); - public onDidDispose = this.didDisposeEmitter.event; - - private ended = false; - private constructor( private readonly socketId: number, private readonly proxy: ExtHostManagedSocketsShape, - private readonly debugLabel: string, - onCloseEmitter: Emitter, - onDataEmitter: Emitter, - onEndEmitter: Emitter, + debugLabel: string, + half: RemoteSocketHalf, ) { - super(); - - this._register(onDataEmitter); - this._register(onDataEmitter.event(data => this.pausableDataEmitter.fire(data))); - - this.onClose = this._register(onCloseEmitter).event; - this.onEnd = this._register(onEndEmitter).event; + super(debugLabel, half); } - /** Pauses data events until a new listener comes in onData() */ - pauseData() { - this.pausableDataEmitter.pause(); - } - - write(buffer: VSBuffer): void { + public override write(buffer: VSBuffer): void { this.proxy.$remoteSocketWrite(this.socketId, buffer); } - end(): void { - this.ended = true; + protected override closeRemote(): void { this.proxy.$remoteSocketEnd(this.socketId); } - drain(): Promise { + public override drain(): Promise { return this.proxy.$remoteSocketDrain(this.socketId); } - - traceSocketEvent(type: SocketDiagnosticsEventType, data?: any): void { - SocketDiagnostics.traceSocketEvent(this, this.debugLabel, type, data); - } - - override dispose(): void { - if (!this.ended) { - this.proxy.$remoteSocketEnd(this.socketId); - } - - this.didDisposeEmitter.fire(); - super.dispose(); - } } diff --git a/src/vs/workbench/api/common/extHostExtensionService.ts b/src/vs/workbench/api/common/extHostExtensionService.ts index 0c35ea254f3..0a0eebdd8a5 100644 --- a/src/vs/workbench/api/common/extHostExtensionService.ts +++ b/src/vs/workbench/api/common/extHostExtensionService.ts @@ -861,9 +861,11 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme performance.mark(`code/extHost/willResolveAuthority/${authorityPrefix}`); result = await resolver.resolve(remoteAuthority, { resolveAttempt, execServer }); performance.mark(`code/extHost/didResolveAuthorityOK/${authorityPrefix}`); - // todo@connor4312: we probably need to chain tunnels too, how does this work with 'public' tunnels? logInfo(`setting tunnel factory...`); - this._register(await this._extHostTunnelService.setTunnelFactory(resolver)); + this._register(await this._extHostTunnelService.setTunnelFactory( + resolver, + ExtHostManagedResolvedAuthority.isManagedResolvedAuthority(result) ? result : undefined + )); } else { logInfo(`invoking resolveExecServer() for ${remoteAuthority}`); performance.mark(`code/extHost/willResolveExecServer/${authorityPrefix}`); diff --git a/src/vs/workbench/api/common/extHostTunnelService.ts b/src/vs/workbench/api/common/extHostTunnelService.ts index 34fed87a677..7040aca80d9 100644 --- a/src/vs/workbench/api/common/extHostTunnelService.ts +++ b/src/vs/workbench/api/common/extHostTunnelService.ts @@ -54,7 +54,7 @@ export interface IExtHostTunnelService extends ExtHostTunnelServiceShape { openTunnel(extension: IExtensionDescription, forward: TunnelOptions): Promise; getTunnels(): Promise; onDidChangeTunnels: vscode.Event; - setTunnelFactory(provider: vscode.RemoteAuthorityResolver | undefined): Promise; + setTunnelFactory(provider: vscode.RemoteAuthorityResolver | undefined, managedRemoteAuthority: vscode.ManagedResolvedAuthority | undefined): Promise; registerPortsAttributesProvider(portSelector: PortAttributesSelector, provider: vscode.PortAttributesProvider): IDisposable; registerTunnelProvider(provider: vscode.TunnelProvider, information: vscode.TunnelInformation): Promise; } @@ -165,7 +165,15 @@ export class ExtHostTunnelService extends Disposable implements IExtHostTunnelSe })); } - async setTunnelFactory(provider: vscode.RemoteAuthorityResolver | undefined): Promise { + /** + * Applies the tunnel metadata and factory found in the remote authority + * resolver to the tunnel system. + * + * `managedRemoteAuthority` should be be passed if the resolver returned on. + * If this is the case, the tunnel cannot be connected to via a websocket from + * the share process, so a synethic tunnel factory is used as a default. + */ + async setTunnelFactory(provider: vscode.RemoteAuthorityResolver | undefined, managedRemoteAuthority: vscode.ManagedResolvedAuthority | undefined): Promise { // Do not wait for any of the proxy promises here. // It will delay startup and there is nothing that needs to be waited for. if (provider) { @@ -176,8 +184,9 @@ export class ExtHostTunnelService extends Disposable implements IExtHostTunnelSe this._showCandidatePort = provider.showCandidatePort; this._proxy.$setCandidateFilter(); } - if (provider.tunnelFactory) { - this._forwardPortProvider = provider.tunnelFactory; + const tunnelFactory = provider.tunnelFactory ?? (managedRemoteAuthority ? this.makeManagedTunnelFactory(managedRemoteAuthority) : undefined); + if (tunnelFactory) { + this._forwardPortProvider = tunnelFactory; let privacyOptions = provider.tunnelFeatures?.privacyOptions ?? []; if (provider.tunnelFeatures?.public && (privacyOptions.length === 0)) { privacyOptions = [ @@ -210,6 +219,10 @@ export class ExtHostTunnelService extends Disposable implements IExtHostTunnelSe }); } + protected makeManagedTunnelFactory(_authority: vscode.ManagedResolvedAuthority): vscode.RemoteAuthorityResolver['tunnelFactory'] { + return undefined; // may be overridden + } + async $closeTunnel(remote: { host: string; port: number }, silent?: boolean): Promise { if (this._extensionTunnels.has(remote.host)) { const hostMap = this._extensionTunnels.get(remote.host)!; diff --git a/src/vs/workbench/api/node/extHost.node.services.ts b/src/vs/workbench/api/node/extHost.node.services.ts index 9a4ffa8b033..582cea087ee 100644 --- a/src/vs/workbench/api/node/extHost.node.services.ts +++ b/src/vs/workbench/api/node/extHost.node.services.ts @@ -24,6 +24,8 @@ import { NodeExtHostVariableResolverProviderService } from 'vs/workbench/api/nod import { IExtHostVariableResolverProvider } from 'vs/workbench/api/common/extHostVariableResolverService'; import { ExtHostLogService } from 'vs/workbench/api/common/extHostLogService'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; +import { ISignService } from 'vs/platform/sign/common/sign'; +import { SignService } from 'vs/platform/sign/node/signService'; // ######################################################################### // ### ### @@ -34,6 +36,7 @@ import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; registerSingleton(IExtHostExtensionService, ExtHostExtensionService, InstantiationType.Eager); registerSingleton(ILoggerService, ExtHostLoggerService, InstantiationType.Delayed); registerSingleton(ILogService, new SyncDescriptor(ExtHostLogService, [false], true)); +registerSingleton(ISignService, SignService, InstantiationType.Delayed); registerSingleton(IExtensionStoragePaths, ExtensionStoragePaths, InstantiationType.Eager); registerSingleton(IExtHostDebugService, ExtHostDebugService, InstantiationType.Eager); diff --git a/src/vs/workbench/api/node/extHostTunnelService.ts b/src/vs/workbench/api/node/extHostTunnelService.ts index 56e0de8c855..561f731654d 100644 --- a/src/vs/workbench/api/node/extHostTunnelService.ts +++ b/src/vs/workbench/api/node/extHostTunnelService.ts @@ -4,17 +4,26 @@ *--------------------------------------------------------------------------------------------*/ import { exec } from 'child_process'; +import { VSBuffer } from 'vs/base/common/buffer'; +import { Emitter } from 'vs/base/common/event'; +import { DisposableStore } from 'vs/base/common/lifecycle'; import { MovingAverage } from 'vs/base/common/numbers'; import { isLinux } from 'vs/base/common/platform'; import * as resources from 'vs/base/common/resources'; import { URI } from 'vs/base/common/uri'; import * as pfs from 'vs/base/node/pfs'; +import { ISocket, SocketCloseEventType } from 'vs/base/parts/ipc/common/ipc.net'; import { ILogService } from 'vs/platform/log/common/log'; +import { ManagedSocket, RemoteSocketHalf, connectManagedSocket } from 'vs/platform/remote/common/managedSocket'; +import { ManagedRemoteConnection } from 'vs/platform/remote/common/remoteAuthorityResolver'; +import { ISignService } from 'vs/platform/sign/common/sign'; import { isAllInterfaces, isLocalhost } from 'vs/platform/tunnel/common/tunnel'; +import { NodeRemoteTunnel } from 'vs/platform/tunnel/node/tunnelService'; import { IExtHostInitDataService } from 'vs/workbench/api/common/extHostInitDataService'; import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService'; import { ExtHostTunnelService } from 'vs/workbench/api/common/extHostTunnelService'; import { CandidatePort } from 'vs/workbench/services/remote/common/tunnelModel'; +import * as vscode from 'vscode'; export function getSockets(stdout: string): Record { const lines = stdout.trim().split('\n'); @@ -171,8 +180,9 @@ export class NodeExtHostTunnelService extends ExtHostTunnelService { constructor( @IExtHostRpcService extHostRpc: IExtHostRpcService, - @IExtHostInitDataService initData: IExtHostInitDataService, - @ILogService logService: ILogService + @IExtHostInitDataService private readonly initData: IExtHostInitDataService, + @ILogService logService: ILogService, + @ISignService private readonly signService: ISignService, ) { super(extHostRpc, initData, logService); if (isLinux && initData.remote.isRemote && initData.remote.authority) { @@ -297,4 +307,102 @@ export class NodeExtHostTunnelService extends ExtHostTunnelService { } }); } + + protected override makeManagedTunnelFactory(authority: vscode.ManagedResolvedAuthority): vscode.RemoteAuthorityResolver['tunnelFactory'] { + return async (tunnelOptions) => { + const t = new NodeRemoteTunnel( + { + commit: this.initData.commit, + quality: this.initData.quality, + logService: this.logService, + ipcLogger: null, + // services and address providers have stubs since we don't need + // the connection identification that the renderer process uses + remoteSocketFactoryService: { + _serviceBrand: undefined, + async connect(_connectTo: ManagedRemoteConnection, path: string, query: string, debugLabel: string): Promise { + const result = await authority.makeConnection(); + return ExtHostManagedSocket.connect(result, path, query, debugLabel); + }, + register() { + throw new Error('not implemented'); + }, + }, + addressProvider: { + getAddress() { + return Promise.resolve({ + connectTo: new ManagedRemoteConnection(0), + connectionToken: authority.connectionToken, + }); + }, + }, + signService: this.signService, + }, + 'localhost', + tunnelOptions.remoteAddress.host || 'localhost', + tunnelOptions.remoteAddress.port, + tunnelOptions.localAddressPort, + ); + + await t.waitForReady(); + + const disposeEmitter = new Emitter(); + + return { + localAddress: t.localAddress, + remoteAddress: { port: t.tunnelRemotePort, host: t.tunnelRemoteHost }, + onDidDispose: disposeEmitter.event, + dispose: () => { + t.dispose(); + disposeEmitter.fire(); + disposeEmitter.dispose(); + }, + }; + }; + } +} + +class ExtHostManagedSocket extends ManagedSocket { + public static connect( + passing: vscode.ManagedMessagePassing, + path: string, query: string, debugLabel: string, + ): Promise { + const d = new DisposableStore(); + const half: RemoteSocketHalf = { + onClose: d.add(new Emitter()), + onData: d.add(new Emitter()), + onEnd: d.add(new Emitter()), + }; + + d.add(passing.onDidReceiveMessage(d => half.onData.fire(VSBuffer.wrap(d)))); + d.add(passing.onDidEnd(() => half.onEnd.fire())); + d.add(passing.onDidClose(error => half.onClose.fire({ + type: SocketCloseEventType.NodeSocketCloseEvent, + error, + hadError: !!error + }))); + + const socket = new ExtHostManagedSocket(passing, debugLabel, half); + socket._register(d); + return connectManagedSocket(socket, path, query, debugLabel, half); + } + + constructor( + private readonly passing: vscode.ManagedMessagePassing, + debugLabel: string, + half: RemoteSocketHalf, + ) { + super(debugLabel, half); + } + + public override write(buffer: VSBuffer): void { + this.passing.send(buffer.buffer); + } + protected override closeRemote(): void { + this.passing.end(); + } + + public override async drain(): Promise { + await this.passing.drain?.(); + } } diff --git a/src/vs/workbench/api/test/browser/mainThreadManagedSockets.test.ts b/src/vs/workbench/api/test/browser/mainThreadManagedSockets.test.ts index 611ec9727c0..6eb1c08ad65 100644 --- a/src/vs/workbench/api/test/browser/mainThreadManagedSockets.test.ts +++ b/src/vs/workbench/api/test/browser/mainThreadManagedSockets.test.ts @@ -10,7 +10,8 @@ import { Emitter } from 'vs/base/common/event'; import { DisposableStore } from 'vs/base/common/lifecycle'; import { SocketCloseEvent } from 'vs/base/parts/ipc/common/ipc.net'; import { mock } from 'vs/base/test/common/mock'; -import { ManagedSocket, RemoteSocketHalf } from 'vs/workbench/api/browser/mainThreadManagedSockets'; +import { RemoteSocketHalf } from 'vs/platform/remote/common/managedSocket'; +import { MainThreadManagedSocket } from 'vs/workbench/api/browser/mainThreadManagedSockets'; import { ExtHostManagedSocketsShape } from 'vs/workbench/api/common/extHost.protocol'; suite('MainThreadManagedSockets', () => { @@ -68,7 +69,7 @@ suite('MainThreadManagedSockets', () => { }); async function doConnect() { - const socket = ManagedSocket.connect(1, extHost, '/hello', 'world=true', '', half); + const socket = MainThreadManagedSocket.connect(1, extHost, '/hello', 'world=true', '', half); await extHost.expectEvent(evt => evt.data && evt.data.startsWith('GET ws://localhost/hello?world=true&skipWebSocketFrames=true HTTP/1.1\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Key:'), 'websocket open event'); half.onData.fire(VSBuffer.fromString('Opened successfully ;)\r\n\r\n')); return await socket; @@ -79,7 +80,7 @@ suite('MainThreadManagedSockets', () => { }); test('includes trailing connection data', async () => { - const socketProm = ManagedSocket.connect(1, extHost, '/hello', 'world=true', '', half); + const socketProm = MainThreadManagedSocket.connect(1, extHost, '/hello', 'world=true', '', half); await extHost.expectEvent(evt => evt.data && evt.data.includes('GET ws://localhost'), 'websocket open event'); half.onData.fire(VSBuffer.fromString('Opened successfully ;)\r\n\r\nSome trailing data')); const socket = await socketProm; From ccf71f1571c764f6144e89f17a599d179f37a3d0 Mon Sep 17 00:00:00 2001 From: meganrogge Date: Wed, 23 Aug 2023 10:43:20 -0700 Subject: [PATCH 133/221] try to fix timing issue --- .../accessibility/browser/accessibilityContributions.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/accessibility/browser/accessibilityContributions.ts b/src/vs/workbench/contrib/accessibility/browser/accessibilityContributions.ts index 3d6968b88c4..1baf82143d4 100644 --- a/src/vs/workbench/contrib/accessibility/browser/accessibilityContributions.ts +++ b/src/vs/workbench/contrib/accessibility/browser/accessibilityContributions.ts @@ -310,10 +310,12 @@ export class InlineCompletionsAccessibleViewContribution extends Disposable { editor.focus(); }, next() { - model.next().then(() => show()); + model.next(); + setTimeout(() => show(), 50); }, previous() { - model.previous().then(() => show()); + model.previous(); + setTimeout(() => show(), 50); }, options: this._options }); From c08c2a789bb3b943e338b5132a81494bb0fbc29a Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Wed, 23 Aug 2023 20:19:44 +0200 Subject: [PATCH 134/221] ignore unexpected dom nodes (#191113) Fixes #169854: ignore surprising dom nodes --- src/vs/editor/browser/controller/mouseTarget.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/vs/editor/browser/controller/mouseTarget.ts b/src/vs/editor/browser/controller/mouseTarget.ts index 0215f9031a6..b39b8f95ba6 100644 --- a/src/vs/editor/browser/controller/mouseTarget.ts +++ b/src/vs/editor/browser/controller/mouseTarget.ts @@ -198,6 +198,13 @@ class ElementPath { ); } + public static isChildOfOverflowGuard(path: Uint8Array): boolean { + return ( + path.length >= 1 + && path[0] === PartFingerprint.OverflowGuard + ); + } + public static isChildOfOverflowingContentWidgets(path: Uint8Array): boolean { return ( path.length >= 1 @@ -538,6 +545,11 @@ export class MouseTargetFactory { let result: IMouseTarget | null = null; + if (!ElementPath.isChildOfOverflowGuard(request.targetPath) && !ElementPath.isChildOfOverflowingContentWidgets(request.targetPath)) { + // We only render dom nodes inside the overflow guard or in the overflowing content widgets + result = result || request.fulfillUnknown(); + } + result = result || MouseTargetFactory._hitTestContentWidget(ctx, resolvedRequest); result = result || MouseTargetFactory._hitTestOverlayWidget(ctx, resolvedRequest); result = result || MouseTargetFactory._hitTestMinimap(ctx, resolvedRequest); From 82643e93f57fe752a587c0537fe4866e2d44eddf Mon Sep 17 00:00:00 2001 From: Justin Chen <54879025+justschen@users.noreply.github.com> Date: Wed, 23 Aug 2023 11:28:35 -0700 Subject: [PATCH 135/221] Changed action widget header ellipses (#191096) changed from ellipses to semi-colons --- .../contrib/codeAction/browser/codeActionMenu.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/vs/editor/contrib/codeAction/browser/codeActionMenu.ts b/src/vs/editor/contrib/codeAction/browser/codeActionMenu.ts index 0f645908a5f..fc33e04fdd0 100644 --- a/src/vs/editor/contrib/codeAction/browser/codeActionMenu.ts +++ b/src/vs/editor/contrib/codeAction/browser/codeActionMenu.ts @@ -22,13 +22,13 @@ interface ActionGroup { const uncategorizedCodeActionGroup = Object.freeze({ kind: CodeActionKind.Empty, title: localize('codeAction.widget.id.more', 'More Actions...') }); const codeActionGroups = Object.freeze([ - { kind: CodeActionKind.QuickFix, title: localize('codeAction.widget.id.quickfix', 'Quick Fix...') }, - { kind: CodeActionKind.RefactorExtract, title: localize('codeAction.widget.id.extract', 'Extract...'), icon: Codicon.wrench }, - { kind: CodeActionKind.RefactorInline, title: localize('codeAction.widget.id.inline', 'Inline...'), icon: Codicon.wrench }, - { kind: CodeActionKind.RefactorRewrite, title: localize('codeAction.widget.id.convert', 'Rewrite...'), icon: Codicon.wrench }, - { kind: CodeActionKind.RefactorMove, title: localize('codeAction.widget.id.move', 'Move...'), icon: Codicon.wrench }, - { kind: CodeActionKind.SurroundWith, title: localize('codeAction.widget.id.surround', 'Surround With...'), icon: Codicon.symbolSnippet }, - { kind: CodeActionKind.Source, title: localize('codeAction.widget.id.source', 'Source Action...'), icon: Codicon.symbolFile }, + { kind: CodeActionKind.QuickFix, title: localize('codeAction.widget.id.quickfix', 'Quick Fix:') }, + { kind: CodeActionKind.RefactorExtract, title: localize('codeAction.widget.id.extract', 'Extract:'), icon: Codicon.wrench }, + { kind: CodeActionKind.RefactorInline, title: localize('codeAction.widget.id.inline', 'Inline:'), icon: Codicon.wrench }, + { kind: CodeActionKind.RefactorRewrite, title: localize('codeAction.widget.id.convert', 'Rewrite:'), icon: Codicon.wrench }, + { kind: CodeActionKind.RefactorMove, title: localize('codeAction.widget.id.move', 'Move:'), icon: Codicon.wrench }, + { kind: CodeActionKind.SurroundWith, title: localize('codeAction.widget.id.surround', 'Surround With:'), icon: Codicon.symbolSnippet }, + { kind: CodeActionKind.Source, title: localize('codeAction.widget.id.source', 'Source Action:'), icon: Codicon.symbolFile }, uncategorizedCodeActionGroup, ]); From c9481326e71e5a842f1addf0cbd181cdb1749d11 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Wed, 23 Aug 2023 20:33:30 +0200 Subject: [PATCH 136/221] Use full line decorations for comment range (#191107) Fixes #188901 --- .../workbench/contrib/comments/browser/commentColors.ts | 2 -- .../comments/browser/commentThreadRangeDecorator.ts | 6 ++++-- .../workbench/contrib/comments/browser/media/review.css | 9 --------- 3 files changed, 4 insertions(+), 13 deletions(-) diff --git a/src/vs/workbench/contrib/comments/browser/commentColors.ts b/src/vs/workbench/contrib/comments/browser/commentColors.ts index bfc70a8a247..a300a745a56 100644 --- a/src/vs/workbench/contrib/comments/browser/commentColors.ts +++ b/src/vs/workbench/contrib/comments/browser/commentColors.ts @@ -15,9 +15,7 @@ const unresolvedCommentViewIcon = registerColor('commentsView.unresolvedIcon', { const resolvedCommentBorder = registerColor('editorCommentsWidget.resolvedBorder', { dark: resolvedCommentViewIcon, light: resolvedCommentViewIcon, hcDark: contrastBorder, hcLight: contrastBorder }, nls.localize('resolvedCommentBorder', 'Color of borders and arrow for resolved comments.')); const unresolvedCommentBorder = registerColor('editorCommentsWidget.unresolvedBorder', { dark: unresolvedCommentViewIcon, light: unresolvedCommentViewIcon, hcDark: contrastBorder, hcLight: contrastBorder }, nls.localize('unresolvedCommentBorder', 'Color of borders and arrow for unresolved comments.')); export const commentThreadRangeBackground = registerColor('editorCommentsWidget.rangeBackground', { dark: transparent(unresolvedCommentBorder, .1), light: transparent(unresolvedCommentBorder, .1), hcDark: transparent(unresolvedCommentBorder, .1), hcLight: transparent(unresolvedCommentBorder, .1) }, nls.localize('commentThreadRangeBackground', 'Color of background for comment ranges.')); -export const commentThreadRangeBorder = registerColor('editorCommentsWidget.rangeBorder', { dark: transparent(unresolvedCommentBorder, .4), light: transparent(unresolvedCommentBorder, .4), hcDark: transparent(unresolvedCommentBorder, .4), hcLight: transparent(unresolvedCommentBorder, .4) }, nls.localize('commentThreadRangeBorder', 'Color of border for comment ranges.')); export const commentThreadRangeActiveBackground = registerColor('editorCommentsWidget.rangeActiveBackground', { dark: transparent(unresolvedCommentBorder, .1), light: transparent(unresolvedCommentBorder, .1), hcDark: transparent(unresolvedCommentBorder, .1), hcLight: transparent(unresolvedCommentBorder, .1) }, nls.localize('commentThreadActiveRangeBackground', 'Color of background for currently selected or hovered comment range.')); -export const commentThreadRangeActiveBorder = registerColor('editorCommentsWidget.rangeActiveBorder', { dark: transparent(unresolvedCommentBorder, .4), light: transparent(unresolvedCommentBorder, .4), hcDark: transparent(unresolvedCommentBorder, .4), hcLight: transparent(unresolvedCommentBorder, .2) }, nls.localize('commentThreadActiveRangeBorder', 'Color of border for currently selected or hovered comment range.')); const commentThreadStateBorderColors = new Map([ [languages.CommentThreadState.Unresolved, unresolvedCommentBorder], diff --git a/src/vs/workbench/contrib/comments/browser/commentThreadRangeDecorator.ts b/src/vs/workbench/contrib/comments/browser/commentThreadRangeDecorator.ts index 0c9828613d2..182a5f3b397 100644 --- a/src/vs/workbench/contrib/comments/browser/commentThreadRangeDecorator.ts +++ b/src/vs/workbench/contrib/comments/browser/commentThreadRangeDecorator.ts @@ -44,7 +44,8 @@ export class CommentThreadRangeDecorator extends Disposable { description: CommentThreadRangeDecorator.description, isWholeLine: false, zIndex: 20, - className: 'comment-thread-range' + className: 'comment-thread-range', + shouldFillLineOnLineBreak: true }; this.decorationOptions = ModelDecorationOptions.createDynamic(decorationOptions); @@ -53,7 +54,8 @@ export class CommentThreadRangeDecorator extends Disposable { description: CommentThreadRangeDecorator.description, isWholeLine: false, zIndex: 20, - className: 'comment-thread-range-current' + className: 'comment-thread-range-current', + shouldFillLineOnLineBreak: true }; this.activeDecorationOptions = ModelDecorationOptions.createDynamic(activeDecorationOptions); diff --git a/src/vs/workbench/contrib/comments/browser/media/review.css b/src/vs/workbench/contrib/comments/browser/media/review.css index dc27b9a50ae..87c845189d8 100644 --- a/src/vs/workbench/contrib/comments/browser/media/review.css +++ b/src/vs/workbench/contrib/comments/browser/media/review.css @@ -487,21 +487,12 @@ div.preview.inline .monaco-editor .comment-range-glyph { background: var(--vscode-editorGutter-commentRangeForeground); } -.monaco-editor .comment-thread-range, -.monaco-editor .comment-thread-range-current { - border-width: 1px; - border-style: solid; - box-sizing: border-box; -} - .monaco-editor .comment-thread-range { background-color: var(--vscode-editorCommentsWidget-rangeBackground); - border-color: var(--vscode-editorCommentsWidget-rangeBorder); } .monaco-editor .comment-thread-range-current { background-color: var(--vscode-editorCommentsWidget-rangeActiveBackground); - border-color: var(--vscode-editorCommentsWidget-rangeActiveBorder); } .monaco-editor .margin-view-overlays .comment-range-glyph.line-hover, From 4e628263ac4b553c6c044bd30762886542a3164d Mon Sep 17 00:00:00 2001 From: Andrea Mah <31675041+andreamah@users.noreply.github.com> Date: Wed, 23 Aug 2023 11:37:09 -0700 Subject: [PATCH 137/221] Add quick search to command center (#191105) * Add quick search to command center Fixes #191088 * Adjust commandCenterOrder * Update src/vs/workbench/contrib/search/browser/search.contribution.ts Co-authored-by: Tyler James Leonhardt --------- Co-authored-by: Tyler James Leonhardt --- .../contrib/search/browser/search.contribution.ts | 10 ++++++++-- .../search/browser/searchActionsTextQuickAccess.ts | 4 ++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/contrib/search/browser/search.contribution.ts b/src/vs/workbench/contrib/search/browser/search.contribution.ts index a48332a48f2..2f9b6d54d73 100644 --- a/src/vs/workbench/contrib/search/browser/search.contribution.ts +++ b/src/vs/workbench/contrib/search/browser/search.contribution.ts @@ -128,8 +128,14 @@ quickAccessRegistry.registerQuickAccessProvider({ ctor: TextSearchQuickAccess, prefix: TEXT_SEARCH_QUICK_ACCESS_PREFIX, contextKey: 'inTextSearchPicker', - placeholder: nls.localize('textSearchPickerPlaceholder', "Search for text in your workspace files."), - helpEntries: [{ description: nls.localize('textSearchPickerHelp', "Show All Text Results (experimental)"), commandId: Constants.QuickTextSearchActionId }] + placeholder: nls.localize('textSearchPickerPlaceholder', "Search for text in your workspace files (experimental)."), + helpEntries: [ + { + description: nls.localize('textSearchPickerHelp', "Search for Text (Experimental)"), + commandId: Constants.QuickTextSearchActionId, + commandCenterOrder: 65, + } + ] }); // Configuration diff --git a/src/vs/workbench/contrib/search/browser/searchActionsTextQuickAccess.ts b/src/vs/workbench/contrib/search/browser/searchActionsTextQuickAccess.ts index ebf0558987d..3971c1f112c 100644 --- a/src/vs/workbench/contrib/search/browser/searchActionsTextQuickAccess.ts +++ b/src/vs/workbench/contrib/search/browser/searchActionsTextQuickAccess.ts @@ -18,8 +18,8 @@ registerAction2(class TextSearchQuickAccessAction extends Action2 { super({ id: Constants.QuickTextSearchActionId, title: { - value: nls.localize('quickTextSearch', "Quick Text Search"), - original: 'Quick Text Search' + value: nls.localize('quickTextSearch', "Quick Text Search (Experimental)"), + original: 'Quick Text Search (Experimental)' }, category, menu: [{ From a8c87ea06b83205ced3c733c64def35e562a089b Mon Sep 17 00:00:00 2001 From: meganrogge Date: Wed, 23 Aug 2023 11:52:23 -0700 Subject: [PATCH 138/221] also go to previous --- .../browser/terminal.accessibility.contribution.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminal.accessibility.contribution.ts b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminal.accessibility.contribution.ts index 61d6cc20f6b..4eb13c439a6 100644 --- a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminal.accessibility.contribution.ts +++ b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminal.accessibility.contribution.ts @@ -193,8 +193,7 @@ registerTerminalAction({ weight: KeybindingWeight.WorkbenchContrib + 2 }, { - primary: KeyMod.CtrlCmd | KeyCode.UpArrow, - mac: { primary: KeyMod.Alt | KeyCode.UpArrow }, + primary: KeyMod.Alt | KeyCode.UpArrow, when: ContextKeyExpr.and(TerminalContextKeys.accessibleBufferFocus, CONTEXT_ACCESSIBILITY_MODE_ENABLED), weight: KeybindingWeight.WorkbenchContrib + 2 } From ca8d21f30bc6ba83f8d37fc1af851c5596b7ab41 Mon Sep 17 00:00:00 2001 From: meganrogge Date: Wed, 23 Aug 2023 11:56:49 -0700 Subject: [PATCH 139/221] add to commands to skip shell --- src/vs/workbench/contrib/terminal/common/terminal.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vs/workbench/contrib/terminal/common/terminal.ts b/src/vs/workbench/contrib/terminal/common/terminal.ts index 6402859667a..46692bccd1b 100644 --- a/src/vs/workbench/contrib/terminal/common/terminal.ts +++ b/src/vs/workbench/contrib/terminal/common/terminal.ts @@ -570,6 +570,7 @@ export const DEFAULT_COMMANDS_TO_SKIP_SHELL: string[] = [ TerminalCommandId.HideSuggestWidget, TerminalCommandId.FocusHover, AccessibilityCommandId.OpenAccessibilityHelp, + TerminalCommandId.FocusAndHideAccessibleBuffer, 'editor.action.toggleTabFocusMode', 'notifications.hideList', 'notifications.hideToasts', From 5113da8cc6110ea815a38238faf7ee5c82dae032 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 23 Aug 2023 21:03:15 +0200 Subject: [PATCH 140/221] voice - better similarity compare of transcription --- .../actions/chatVoiceInputActions.ts | 31 ++++++++++++++----- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/src/vs/workbench/contrib/chat/electron-sandbox/actions/chatVoiceInputActions.ts b/src/vs/workbench/contrib/chat/electron-sandbox/actions/chatVoiceInputActions.ts index 2ebbbb79bf0..f4d874d252d 100644 --- a/src/vs/workbench/contrib/chat/electron-sandbox/actions/chatVoiceInputActions.ts +++ b/src/vs/workbench/contrib/chat/electron-sandbox/actions/chatVoiceInputActions.ts @@ -76,22 +76,23 @@ class ChatVoiceInputSession { this.chatVoiceInputInProgressKey.set(true); let lastText: string | undefined = undefined; - let lastTextEqualCount = 0; + let lastTextSimilarCount = 0; this.currentChatVoiceInputSession.add(onDidTranscribe(text => { if (text) { - if (lastText && equalsIgnoreCase(text, lastText)) { - lastTextEqualCount++; - - if (lastTextEqualCount >= 2) { - context.widget.acceptInput(); - } + if (lastText && this.isSimilarTranscription(text, lastText)) { + lastTextSimilarCount++; } else { - lastTextEqualCount = 0; + lastTextSimilarCount = 0; lastText = text; + } + if (lastTextSimilarCount >= 2) { + context.widget.acceptInput(); + } else { context.widget.updateInput(text); } + } })); @@ -100,6 +101,20 @@ class ChatVoiceInputSession { })); } + private isSimilarTranscription(textA: string, textB: string): boolean { + + // Attempt to compare the 2 strings in a way to see + // if they are similar or not. As such we: + // - ignore trailing punctuation + // - collapse all whitespace + // - compare case insensitive + + return equalsIgnoreCase( + textA.replace(/[.,;:!?]+$/, '').replace(/\s+/g, ''), + textB.replace(/[.,;:!?]+$/, '').replace(/\s+/g, '') + ); + } + stop(): void { if (!this.currentChatVoiceInputSession) { return; From fe71c9a5eba39efa9bcc9c80fa8928e496842dbe Mon Sep 17 00:00:00 2001 From: meganrogge Date: Wed, 23 Aug 2023 12:48:54 -0700 Subject: [PATCH 141/221] fix #188926 --- .../browser/terminalAccessibleBuffer.ts | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts index fab258f94e6..3e1d2ad466d 100644 --- a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts +++ b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts @@ -14,6 +14,7 @@ import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IQuickInputService, IQuickPick, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput'; import { ITerminalCommand, TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities'; +import { ICurrentPartialCommand } from 'vs/platform/terminal/common/capabilities/commandDetectionCapability'; import { ITerminalLogService } from 'vs/platform/terminal/common/terminal'; import { ITerminalInstance, ITerminalService, IXtermTerminal } from 'vs/workbench/contrib/terminal/browser/terminal'; import { TerminalContextKeys } from 'vs/workbench/contrib/terminal/common/terminalContextKey'; @@ -91,9 +92,9 @@ export class AccessibleBufferWidget extends TerminalAccessibleWidget { this._resetPosition(); } - private _getEditorLineForCommand(command: ITerminalCommand): number | undefined { - let line = command.marker?.line; - if (line === undefined || !command.command.length || line < 0) { + private _getEditorLineForCommand(command: ITerminalCommand | ICurrentPartialCommand): number | undefined { + let line = 'marker' in command ? command.marker?.line : 'commandStartMarker' in command ? command.commandStartMarker?.line : undefined; + if (line === undefined || line < 0) { return; } line = this._bufferTracker.bufferToEditorLineMapping.get(line); @@ -105,6 +106,7 @@ export class AccessibleBufferWidget extends TerminalAccessibleWidget { private _getCommandsWithEditorLine(): ICommandWithEditorLine[] | undefined { const commands = this._instance.capabilities.get(TerminalCapability.CommandDetection)?.commands; + const currentCommand = this._instance.capabilities.get(TerminalCapability.CommandDetection)?.currentCommand; if (!commands?.length) { return; } @@ -116,6 +118,12 @@ export class AccessibleBufferWidget extends TerminalAccessibleWidget { } result.push({ command, lineNumber }); } + if (currentCommand) { + const lineNumber = this._getEditorLineForCommand(currentCommand); + if (!!lineNumber) { + result.push({ command: currentCommand, lineNumber }); + } + } return result; } @@ -135,7 +143,7 @@ export class AccessibleBufferWidget extends TerminalAccessibleWidget { { label: localize('terminal.integrated.symbolQuickPick.labelNoExitCode', '{0}', command.command), lineNumber, - exitCode: command.exitCode + exitCode: 'exitCode' in command ? command.exitCode : undefined }); } const quickPick = this._quickInputService.createQuickPick(); @@ -261,5 +269,5 @@ export class AccessibleBufferWidget extends TerminalAccessibleWidget { } } -interface ICommandWithEditorLine { command: ITerminalCommand; lineNumber: number } +interface ICommandWithEditorLine { command: ITerminalCommand | ICurrentPartialCommand; lineNumber: number } From 330fb1f905f91294f9fe124bcba8a154ec96dc54 Mon Sep 17 00:00:00 2001 From: Andrea Mah <31675041+andreamah@users.noreply.github.com> Date: Wed, 23 Aug 2023 13:37:12 -0700 Subject: [PATCH 142/221] Handle right arrow on quick search menu (#191115) Fixes #191110 --- .../quickTextSearch/textSearchQuickAccess.ts | 67 +++++++++++++------ .../contrib/search/browser/searchView.ts | 2 +- .../contrib/search/common/constants.ts | 2 +- 3 files changed, 50 insertions(+), 21 deletions(-) diff --git a/src/vs/workbench/contrib/search/browser/quickTextSearch/textSearchQuickAccess.ts b/src/vs/workbench/contrib/search/browser/quickTextSearch/textSearchQuickAccess.ts index 15a82a6cf6a..d17d209b9b1 100644 --- a/src/vs/workbench/contrib/search/browser/quickTextSearch/textSearchQuickAccess.ts +++ b/src/vs/workbench/contrib/search/browser/quickTextSearch/textSearchQuickAccess.ts @@ -7,22 +7,26 @@ import { IMatch } from 'vs/base/common/filters'; import { DisposableStore } from 'vs/base/common/lifecycle'; import { basenameOrAuthority, dirname } from 'vs/base/common/resources'; import { ThemeIcon } from 'vs/base/common/themables'; +import { IRange, Range } from 'vs/editor/common/core/range'; import { localize } from 'vs/nls'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { ITextEditorSelection } from 'vs/platform/editor/common/editor'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { ILabelService } from 'vs/platform/label/common/label'; import { WorkbenchCompressibleObjectTree, getSelectionKeyboardEvent } from 'vs/platform/list/browser/listService'; import { FastAndSlowPicks, IPickerQuickAccessItem, PickerQuickAccessProvider, Picks } from 'vs/platform/quickinput/browser/pickerQuickAccess'; -import { IQuickPickItem, IQuickPickSeparator } from 'vs/platform/quickinput/common/quickInput'; +import { IKeyMods, IQuickPickItem, IQuickPickSeparator } from 'vs/platform/quickinput/common/quickInput'; import { IWorkspaceContextService, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; +import { IWorkbenchQuickAccessConfiguration } from 'vs/workbench/browser/quickaccess'; +import { IWorkbenchEditorConfiguration } from 'vs/workbench/common/editor'; import { IViewsService } from 'vs/workbench/common/views'; import { searchDetailsIcon, searchOpenInFileIcon } from 'vs/workbench/contrib/search/browser/searchIcons'; import { FileMatch, Match, MatchInNotebook, RenderableMatch, SearchModel, searchComparer } from 'vs/workbench/contrib/search/browser/searchModel'; import { SearchView, getEditorSelectionFromMatch } from 'vs/workbench/contrib/search/browser/searchView'; -import { getOutOfWorkspaceEditorResources } from 'vs/workbench/contrib/search/common/search'; -import { ACTIVE_GROUP, IEditorService } from 'vs/workbench/services/editor/common/editorService'; +import { IWorkbenchSearchConfiguration, getOutOfWorkspaceEditorResources } from 'vs/workbench/contrib/search/common/search'; +import { ACTIVE_GROUP, IEditorService, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService'; import { ITextQueryBuilderOptions, QueryBuilder } from 'vs/workbench/services/search/common/queryBuilder'; -import { IPatternInfo, ISearchConfigurationProperties, ITextQuery, VIEW_ID } from 'vs/workbench/services/search/common/search'; +import { IPatternInfo, ITextQuery, VIEW_ID } from 'vs/workbench/services/search/common/search'; export const TEXT_SEARCH_QUICK_ACCESS_PREFIX = '% '; @@ -46,8 +50,8 @@ export class TextSearchQuickAccess extends PickerQuickAccessProvider('search'); + private get configuration() { + const editorConfig = this._configurationService.getValue().workbench?.editor; + const searchConfig = this._configurationService.getValue().search; + const quickAccessConfig = this._configurationService.getValue().workbench.quickOpen; + + return { + openEditorPinned: !editorConfig?.enablePreviewFromQuickOpen || !editorConfig?.enablePreview, + preserveInput: quickAccessConfig.preserveInput, + maxResults: searchConfig.maxResults, + smartCase: searchConfig.smartCase, + }; } private doSearch(contentPattern: string, token: CancellationToken): { @@ -170,11 +183,7 @@ export class TextSearchQuickAccess extends PickerQuickAccessProvider { - await this._editorService.openEditor({ - resource: fileMatch.resource, - options - }, ACTIVE_GROUP); - }, + accept: async (keyMods, event) => { + await this.handleAccept(fileMatch, { + keyMods, + selection: getEditorSelectionFromMatch(element, this.searchModel), + preserveFocus: event.inBackground, + forcePinned: event.inBackground, + indexedCellOptions: element instanceof MatchInNotebook ? { index: element.cellIndex, selection: element.range() } : undefined + }); + } }); } } return picks; } + + private async handleAccept(fileMatch: FileMatch, options: { keyMods?: IKeyMods; selection?: ITextEditorSelection; preserveFocus?: boolean; range?: IRange; forcePinned?: boolean; forceOpenSideBySide?: boolean; indexedCellOptions?: { index: number; selection?: Range } }): Promise { + const editorOptions = { + preserveFocus: options.preserveFocus, + pinned: options.keyMods?.ctrlCmd || options.forcePinned || this.configuration.openEditorPinned, + selection: options.selection + }; + + // from https://github.com/microsoft/vscode/blob/f40dabca07a1622b2a0ae3ee741cfc94ab964bef/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts#L1037 + const targetGroup = options.keyMods?.alt || (this.configuration.openEditorPinned && options.keyMods?.ctrlCmd) || options.forceOpenSideBySide ? SIDE_GROUP : ACTIVE_GROUP; + + await this._editorService.openEditor({ + resource: fileMatch.resource, + options: editorOptions + }, targetGroup); + } + protected _getPicks(contentPattern: string, disposables: DisposableStore, token: CancellationToken): Picks | Promise | FastAndSlowPicks> | FastAndSlowPicks | null { const allMatches = this.doSearch(contentPattern, token); diff --git a/src/vs/workbench/contrib/search/browser/searchView.ts b/src/vs/workbench/contrib/search/browser/searchView.ts index 07576765667..4cdc0341049 100644 --- a/src/vs/workbench/contrib/search/browser/searchView.ts +++ b/src/vs/workbench/contrib/search/browser/searchView.ts @@ -1894,7 +1894,7 @@ export class SearchView extends ViewPane { pinned, selection, revealIfVisible: true, - indexedCellOptions: element instanceof MatchInNotebook ? { cellIndex: element.cellIndex, selection: element.range } : undefined, + indexedCellOptions: element instanceof MatchInNotebook ? { index: element.cellIndex, selection: element.range() } : undefined, }; try { diff --git a/src/vs/workbench/contrib/search/common/constants.ts b/src/vs/workbench/contrib/search/common/constants.ts index d6e4fd9d7a9..1f98bc77b35 100644 --- a/src/vs/workbench/contrib/search/common/constants.ts +++ b/src/vs/workbench/contrib/search/common/constants.ts @@ -30,7 +30,7 @@ export const AddCursorsAtSearchResults = 'addCursorsAtSearchResults'; export const RevealInSideBarForSearchResults = 'search.action.revealInSideBar'; export const ReplaceInFilesActionId = 'workbench.action.replaceInFiles'; export const ShowAllSymbolsActionId = 'workbench.action.showAllSymbols'; -export const QuickTextSearchActionId = 'workbench.action.quickTextSearch'; +export const QuickTextSearchActionId = 'workbench.action.experimental.quickTextSearch'; export const CancelSearchActionId = 'search.action.cancel'; export const RefreshSearchResultsActionId = 'search.action.refreshSearchResults'; export const FocusNextSearchResultActionId = 'search.action.focusNextSearchResult'; From 9b9b9d57917db6495d9e49255682a03173933abe Mon Sep 17 00:00:00 2001 From: meganrogge Date: Wed, 23 Aug 2023 13:41:33 -0700 Subject: [PATCH 143/221] use correct line number --- .../accessibility/browser/textAreaSyncAddon.ts | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/textAreaSyncAddon.ts b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/textAreaSyncAddon.ts index 666f27389d9..379d6965b0a 100644 --- a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/textAreaSyncAddon.ts +++ b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/textAreaSyncAddon.ts @@ -91,23 +91,22 @@ export class TextAreaSyncAddon extends Disposable implements ITerminalAddon { return; } const buffer = this._terminal.buffer.active; - const line = buffer.getLine(buffer.cursorY)?.translateToString(true); + const lineNumber = currentCommand.commandStartMarker?.line; + if (!lineNumber) { + return; + } + const line = buffer.getLine(lineNumber)?.translateToString(true); if (!line) { this._logService.debug(`TextAreaSyncAddon#updateCommandAndCursor: no line`); return; } - if (currentCommand.commandStartX !== undefined) { - // Left prompt + if (!!currentCommand.commandStartX) { this._currentCommand = line.substring(currentCommand.commandStartX); this._cursorX = buffer.cursorX - currentCommand.commandStartX; - } else if (currentCommand.commandRightPromptStartX !== undefined) { - // Right prompt - this._currentCommand = line.substring(0, currentCommand.commandRightPromptStartX); - this._cursorX = buffer.cursorX; } else { this._currentCommand = undefined; this._cursorX = undefined; - this._logService.debug(`TextAreaSyncAddon#updateCommandAndCursor: neither commandStartX nor commandRightPromptStartX`); + this._logService.debug(`TextAreaSyncAddon#updateCommandAndCursor: no commandStartX`); } } } From f96904ece94d72dc9b42db69444fdcf84608d80a Mon Sep 17 00:00:00 2001 From: meganrogge Date: Wed, 23 Aug 2023 13:47:57 -0700 Subject: [PATCH 144/221] don't use messy inline --- .../accessibility/browser/terminalAccessibleBuffer.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts index 3e1d2ad466d..0835367c86e 100644 --- a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts +++ b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts @@ -93,7 +93,12 @@ export class AccessibleBufferWidget extends TerminalAccessibleWidget { } private _getEditorLineForCommand(command: ITerminalCommand | ICurrentPartialCommand): number | undefined { - let line = 'marker' in command ? command.marker?.line : 'commandStartMarker' in command ? command.commandStartMarker?.line : undefined; + let line: number | undefined; + if ('marker' in command) { + line = command.marker?.line; + } else if ('commandStartMarker' in command) { + line = command.commandStartMarker?.line; + } if (line === undefined || line < 0) { return; } From eca80ba5f50d404a09e7b02c1bbf24bb94211069 Mon Sep 17 00:00:00 2001 From: meganrogge Date: Wed, 23 Aug 2023 13:49:01 -0700 Subject: [PATCH 145/221] better names --- .../accessibility/browser/textAreaSyncAddon.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/textAreaSyncAddon.ts b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/textAreaSyncAddon.ts index 379d6965b0a..9916a6f60d0 100644 --- a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/textAreaSyncAddon.ts +++ b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/textAreaSyncAddon.ts @@ -95,13 +95,13 @@ export class TextAreaSyncAddon extends Disposable implements ITerminalAddon { if (!lineNumber) { return; } - const line = buffer.getLine(lineNumber)?.translateToString(true); - if (!line) { + const commandLine = buffer.getLine(lineNumber)?.translateToString(true); + if (!commandLine) { this._logService.debug(`TextAreaSyncAddon#updateCommandAndCursor: no line`); return; } if (!!currentCommand.commandStartX) { - this._currentCommand = line.substring(currentCommand.commandStartX); + this._currentCommand = commandLine.substring(currentCommand.commandStartX); this._cursorX = buffer.cursorX - currentCommand.commandStartX; } else { this._currentCommand = undefined; From 557695b920d4779d63e80d9d1597dc57d9b2a7c2 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Wed, 23 Aug 2023 14:10:55 -0700 Subject: [PATCH 146/221] Fix inlay hint location (#191122) --- .../src/languageFeatures/inlayHints.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/extensions/typescript-language-features/src/languageFeatures/inlayHints.ts b/extensions/typescript-language-features/src/languageFeatures/inlayHints.ts index 5363619579b..1b9d554688d 100644 --- a/extensions/typescript-language-features/src/languageFeatures/inlayHints.ts +++ b/extensions/typescript-language-features/src/languageFeatures/inlayHints.ts @@ -77,7 +77,7 @@ class TypeScriptInlayHintsProvider extends Disposable implements vscode.InlayHin return response.body.map(hint => { const result = new vscode.InlayHint( Position.fromLocation(hint.position), - this.convertInlayHintText(model.uri, hint), + this.convertInlayHintText(hint), hint.kind && fromProtocolInlayHintKind(hint.kind) ); result.paddingLeft = hint.whitespaceBefore; @@ -86,19 +86,18 @@ class TypeScriptInlayHintsProvider extends Disposable implements vscode.InlayHin }); } - private convertInlayHintText(resource: vscode.Uri, tsHint: Proto.InlayHintItem): string | vscode.InlayHintLabelPart[] { + private convertInlayHintText(tsHint: Proto.InlayHintItem): string | vscode.InlayHintLabelPart[] { if (tsHint.displayParts) { return tsHint.displayParts.map((part): vscode.InlayHintLabelPart => { const out = new vscode.InlayHintLabelPart(part.text); if (part.span) { - out.location = Location.fromTextSpan(resource, part.span); + out.location = Location.fromTextSpan(this.client.toResource(part.span.file), part.span); } return out; }); } return tsHint.text; - } } From f605341af6b083f2b6d9c853d882b96955c690b7 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Wed, 23 Aug 2023 23:17:23 +0200 Subject: [PATCH 147/221] Syntax highlighting incorrect in vscode.python for the word 'file' (#191111) * Syntax highlighting incorrect in vscode.python for the word 'file' Fixes #188190 * Update colorization test --- extensions/theme-defaults/themes/dark_vs.json | 1 + .../theme-defaults/themes/hc_black.json | 3 +- .../theme-defaults/themes/hc_light.json | 6 +++- .../theme-defaults/themes/light_vs.json | 3 +- .../themes/kimbie-dark-color-theme.json | 3 +- .../themes/dimmed-monokai-color-theme.json | 3 +- .../themes/monokai-color-theme.json | 3 +- .../themes/quietlight-color-theme.json | 3 +- .../theme-red/themes/Red-color-theme.json | 3 +- .../themes/solarized-dark-color-theme.json | 3 +- .../themes/solarized-light-color-theme.json | 3 +- .../tomorrow-night-blue-color-theme.json | 3 +- .../test/colorize-results/test_py.json | 32 +++++++++---------- 13 files changed, 42 insertions(+), 27 deletions(-) diff --git a/extensions/theme-defaults/themes/dark_vs.json b/extensions/theme-defaults/themes/dark_vs.json index 21af2d3cf3a..2b9f0d5a5ab 100644 --- a/extensions/theme-defaults/themes/dark_vs.json +++ b/extensions/theme-defaults/themes/dark_vs.json @@ -34,6 +34,7 @@ "meta.embedded", "source.groovy.embedded", "string meta.image.inline.markdown", + "variable.legacy.builtin.python" ], "settings": { "foreground": "#D4D4D4" diff --git a/extensions/theme-defaults/themes/hc_black.json b/extensions/theme-defaults/themes/hc_black.json index 26dadd320a0..816fbf9395a 100644 --- a/extensions/theme-defaults/themes/hc_black.json +++ b/extensions/theme-defaults/themes/hc_black.json @@ -19,7 +19,8 @@ "scope": [ "meta.embedded", "source.groovy.embedded", - "string meta.image.inline.markdown" + "string meta.image.inline.markdown", + "variable.legacy.builtin.python" ], "settings": { "foreground": "#FFFFFF" diff --git a/extensions/theme-defaults/themes/hc_light.json b/extensions/theme-defaults/themes/hc_light.json index fde5393f070..17c1af9ef34 100644 --- a/extensions/theme-defaults/themes/hc_light.json +++ b/extensions/theme-defaults/themes/hc_light.json @@ -3,7 +3,11 @@ "name": "Light High Contrast", "tokenColors": [ { - "scope": ["meta.embedded", "source.groovy.embedded"], + "scope": [ + "meta.embedded", + "source.groovy.embedded", + "variable.legacy.builtin.python" + ], "settings": { "foreground": "#292929" } diff --git a/extensions/theme-defaults/themes/light_vs.json b/extensions/theme-defaults/themes/light_vs.json index 301730e078e..5e2d5a7889e 100644 --- a/extensions/theme-defaults/themes/light_vs.json +++ b/extensions/theme-defaults/themes/light_vs.json @@ -38,7 +38,8 @@ "scope": [ "meta.embedded", "source.groovy.embedded", - "string meta.image.inline.markdown" + "string meta.image.inline.markdown", + "variable.legacy.builtin.python" ], "settings": { "foreground": "#000000ff" diff --git a/extensions/theme-kimbie-dark/themes/kimbie-dark-color-theme.json b/extensions/theme-kimbie-dark/themes/kimbie-dark-color-theme.json index eeb4eeb6b88..3554c486209 100644 --- a/extensions/theme-kimbie-dark/themes/kimbie-dark-color-theme.json +++ b/extensions/theme-kimbie-dark/themes/kimbie-dark-color-theme.json @@ -64,7 +64,8 @@ "scope": [ "meta.embedded", "source.groovy.embedded", - "string meta.image.inline.markdown" + "string meta.image.inline.markdown", + "variable.legacy.builtin.python" ], "settings": { "foreground": "#d3af86" diff --git a/extensions/theme-monokai-dimmed/themes/dimmed-monokai-color-theme.json b/extensions/theme-monokai-dimmed/themes/dimmed-monokai-color-theme.json index ea84bededd5..691680512a4 100644 --- a/extensions/theme-monokai-dimmed/themes/dimmed-monokai-color-theme.json +++ b/extensions/theme-monokai-dimmed/themes/dimmed-monokai-color-theme.json @@ -71,7 +71,8 @@ { "scope": [ "meta.embedded", - "source.groovy.embedded" + "source.groovy.embedded", + "variable.legacy.builtin.python" ], "settings": { "foreground": "#C5C8C6" diff --git a/extensions/theme-monokai/themes/monokai-color-theme.json b/extensions/theme-monokai/themes/monokai-color-theme.json index 6489b0dd39c..9a510748714 100644 --- a/extensions/theme-monokai/themes/monokai-color-theme.json +++ b/extensions/theme-monokai/themes/monokai-color-theme.json @@ -111,7 +111,8 @@ "scope": [ "meta.embedded", "source.groovy.embedded", - "string meta.image.inline.markdown" + "string meta.image.inline.markdown", + "variable.legacy.builtin.python" ], "settings": { "foreground": "#F8F8F2" diff --git a/extensions/theme-quietlight/themes/quietlight-color-theme.json b/extensions/theme-quietlight/themes/quietlight-color-theme.json index 9d55f2e362b..3705ed48608 100644 --- a/extensions/theme-quietlight/themes/quietlight-color-theme.json +++ b/extensions/theme-quietlight/themes/quietlight-color-theme.json @@ -10,7 +10,8 @@ "scope": [ "meta.embedded", "source.groovy.embedded", - "string meta.image.inline.markdown" + "string meta.image.inline.markdown", + "variable.legacy.builtin.python" ], "settings": { "foreground": "#333333" diff --git a/extensions/theme-red/themes/Red-color-theme.json b/extensions/theme-red/themes/Red-color-theme.json index c139400dc56..233fd9e83da 100644 --- a/extensions/theme-red/themes/Red-color-theme.json +++ b/extensions/theme-red/themes/Red-color-theme.json @@ -70,7 +70,8 @@ "scope": [ "meta.embedded", "source.groovy.embedded", - "string meta.image.inline.markdown" + "string meta.image.inline.markdown", + "variable.legacy.builtin.python" ], "settings": { "foreground": "#F8F8F8" diff --git a/extensions/theme-solarized-dark/themes/solarized-dark-color-theme.json b/extensions/theme-solarized-dark/themes/solarized-dark-color-theme.json index e10c6e67403..e67135a9d99 100644 --- a/extensions/theme-solarized-dark/themes/solarized-dark-color-theme.json +++ b/extensions/theme-solarized-dark/themes/solarized-dark-color-theme.json @@ -10,7 +10,8 @@ "scope": [ "meta.embedded", "source.groovy.embedded", - "string meta.image.inline.markdown" + "string meta.image.inline.markdown", + "variable.legacy.builtin.python" ], "settings": { "foreground": "#839496" diff --git a/extensions/theme-solarized-light/themes/solarized-light-color-theme.json b/extensions/theme-solarized-light/themes/solarized-light-color-theme.json index 8b4074c9a07..d5f6dc11bf0 100644 --- a/extensions/theme-solarized-light/themes/solarized-light-color-theme.json +++ b/extensions/theme-solarized-light/themes/solarized-light-color-theme.json @@ -10,7 +10,8 @@ "scope": [ "meta.embedded", "source.groovy.embedded", - "string meta.image.inline.markdown" + "string meta.image.inline.markdown", + "variable.legacy.builtin.python" ], "settings": { "foreground": "#657B83" diff --git a/extensions/theme-tomorrow-night-blue/themes/tomorrow-night-blue-color-theme.json b/extensions/theme-tomorrow-night-blue/themes/tomorrow-night-blue-color-theme.json index 8e24e6fe4de..b0bdf8e90a9 100644 --- a/extensions/theme-tomorrow-night-blue/themes/tomorrow-night-blue-color-theme.json +++ b/extensions/theme-tomorrow-night-blue/themes/tomorrow-night-blue-color-theme.json @@ -70,7 +70,8 @@ "meta.embedded", "source.groovy.embedded", "meta.jsx.children", - "string meta.image.inline.markdown" + "string meta.image.inline.markdown", + "variable.legacy.builtin.python" ], "settings": { //"background": "#002451", diff --git a/extensions/vscode-colorize-tests/test/colorize-results/test_py.json b/extensions/vscode-colorize-tests/test/colorize-results/test_py.json index e858cd5f201..e8d718cad72 100644 --- a/extensions/vscode-colorize-tests/test/colorize-results/test_py.json +++ b/extensions/vscode-colorize-tests/test/colorize-results/test_py.json @@ -1907,14 +1907,14 @@ "c": "reduce", "t": "source.python meta.function-call.python variable.legacy.builtin.python", "r": { - "dark_plus": "variable: #9CDCFE", - "light_plus": "variable: #001080", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "variable: #9CDCFE", - "dark_modern": "variable: #9CDCFE", - "hc_light": "variable: #001080", - "light_modern": "variable: #001080" + "dark_plus": "variable.legacy.builtin.python: #D4D4D4", + "light_plus": "variable.legacy.builtin.python: #000000", + "dark_vs": "variable.legacy.builtin.python: #D4D4D4", + "light_vs": "variable.legacy.builtin.python: #000000", + "hc_black": "variable.legacy.builtin.python: #FFFFFF", + "dark_modern": "variable.legacy.builtin.python: #D4D4D4", + "hc_light": "variable.legacy.builtin.python: #292929", + "light_modern": "variable.legacy.builtin.python: #000000" } }, { @@ -6233,14 +6233,14 @@ "c": "raw_input", "t": "source.python meta.function-call.python variable.legacy.builtin.python", "r": { - "dark_plus": "variable: #9CDCFE", - "light_plus": "variable: #001080", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "variable: #9CDCFE", - "dark_modern": "variable: #9CDCFE", - "hc_light": "variable: #001080", - "light_modern": "variable: #001080" + "dark_plus": "variable.legacy.builtin.python: #D4D4D4", + "light_plus": "variable.legacy.builtin.python: #000000", + "dark_vs": "variable.legacy.builtin.python: #D4D4D4", + "light_vs": "variable.legacy.builtin.python: #000000", + "hc_black": "variable.legacy.builtin.python: #FFFFFF", + "dark_modern": "variable.legacy.builtin.python: #D4D4D4", + "hc_light": "variable.legacy.builtin.python: #292929", + "light_modern": "variable.legacy.builtin.python: #000000" } }, { From 9f9ac662035fb28bac3d373d1385f2f0cf24143f Mon Sep 17 00:00:00 2001 From: Andrea Mah <31675041+andreamah@users.noreply.github.com> Date: Wed, 23 Aug 2023 14:35:50 -0700 Subject: [PATCH 148/221] notebook-related bugfixes for quick search (#191130) --- .../quickTextSearch/textSearchQuickAccess.ts | 4 ++++ .../contrib/search/browser/searchModel.ts | 21 +++++++++++-------- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/vs/workbench/contrib/search/browser/quickTextSearch/textSearchQuickAccess.ts b/src/vs/workbench/contrib/search/browser/quickTextSearch/textSearchQuickAccess.ts index d17d209b9b1..d01ad5ad73b 100644 --- a/src/vs/workbench/contrib/search/browser/quickTextSearch/textSearchQuickAccess.ts +++ b/src/vs/workbench/contrib/search/browser/quickTextSearch/textSearchQuickAccess.ts @@ -230,6 +230,10 @@ export class TextSearchQuickAccess extends PickerQuickAccessProvider | Promise | FastAndSlowPicks> | FastAndSlowPicks | null { + if (contentPattern === '') { + this.searchModel.searchResult.clear(); + return []; + } const allMatches = this.doSearch(contentPattern, token); if (!allMatches) { diff --git a/src/vs/workbench/contrib/search/browser/searchModel.ts b/src/vs/workbench/contrib/search/browser/searchModel.ts index 95a4644baf4..0d8c8ec06c0 100644 --- a/src/vs/workbench/contrib/search/browser/searchModel.ts +++ b/src/vs/workbench/contrib/search/browser/searchModel.ts @@ -1142,13 +1142,16 @@ export class FolderMatch extends Disposable { raw.forEach(rawFileMatch => { const existingFileMatch = this.getDownstreamFileMatch(rawFileMatch.resource); if (existingFileMatch) { - rawFileMatch - .results! - .filter(resultIsMatch) - .forEach(m => { - textSearchResultToMatches(m, existingFileMatch) - .forEach(m => existingFileMatch.add(m)); - }); + + if (rawFileMatch.results) { + rawFileMatch + .results + .filter(resultIsMatch) + .forEach(m => { + textSearchResultToMatches(m, existingFileMatch) + .forEach(m => existingFileMatch.add(m)); + }); + } // add cell matches if (isIFileMatchWithCells(rawFileMatch)) { @@ -2009,7 +2012,7 @@ export class SearchModel extends Disposable { } { const asyncGenerateOnProgress = async (p: ISearchProgressItem) => { progressEmitter.fire(); - this.onSearchProgress(p, searchInstanceID); + this.onSearchProgress(p, searchInstanceID, false); onProgress?.(p); }; @@ -2020,7 +2023,7 @@ export class SearchModel extends Disposable { }; const tokenSource = this.currentCancelTokenSource = new CancellationTokenSource(callerToken); - const notebookResult = this.notebookSearchService.notebookSearch(query, tokenSource.token, searchInstanceID, syncGenerateOnProgress); + const notebookResult = this.notebookSearchService.notebookSearch(query, tokenSource.token, searchInstanceID, asyncGenerateOnProgress); const textResult = this.searchService.textSearchSplitSyncAsync( searchQuery, this.currentCancelTokenSource.token, asyncGenerateOnProgress, From d91da92c704ab5a054a12566a7c147853e13ed47 Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Wed, 23 Aug 2023 14:36:39 -0700 Subject: [PATCH 149/221] testing: fix treatment of first child test items (#191131) Fixes #190976 --- .../testing/browser/explorerProjections/treeProjection.ts | 4 ++-- .../workbench/contrib/testing/browser/testingExplorerView.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/contrib/testing/browser/explorerProjections/treeProjection.ts b/src/vs/workbench/contrib/testing/browser/explorerProjections/treeProjection.ts index fe492af83eb..3e67da4150b 100644 --- a/src/vs/workbench/contrib/testing/browser/explorerProjections/treeProjection.ts +++ b/src/vs/workbench/contrib/testing/browser/explorerProjections/treeProjection.ts @@ -224,7 +224,7 @@ export class TreeProjection extends Disposable implements ITestTreeProjection { } // The first element will cause the root to be hidden - const affectsRootElement = toRemove.parent?.children.size === 1; + const affectsRootElement = toRemove.depth === 1 && toRemove.parent?.children.size === 1; this.changedParents.add(affectsRootElement ? null : toRemove.parent); const queue: Iterable[] = [[toRemove]]; @@ -302,7 +302,7 @@ export class TreeProjection extends Disposable implements ITestTreeProjection { this.items.set(treeElement.test.item.extId, treeElement); // The first element will cause the root to be shown - const affectsRootElement = treeElement.parent?.children.size === 1; + const affectsRootElement = treeElement.depth === 1 && treeElement.parent?.children.size === 1; this.changedParents.add(affectsRootElement ? null : treeElement.parent); if (treeElement.depth === 0 || isCollapsedInSerializedTestTree(this.lastState, treeElement.test.item.extId) === false) { diff --git a/src/vs/workbench/contrib/testing/browser/testingExplorerView.ts b/src/vs/workbench/contrib/testing/browser/testingExplorerView.ts index 5080d93ece2..84e09da8c8f 100644 --- a/src/vs/workbench/contrib/testing/browser/testingExplorerView.ts +++ b/src/vs/workbench/contrib/testing/browser/testingExplorerView.ts @@ -993,7 +993,7 @@ class TestingExplorerViewModel extends Disposable { this.projection.value = this.instantiationService.createInstance(TreeProjection, lastState); } - const scheduler = new RunOnceScheduler(() => this.applyProjectionChanges(), 200); + const scheduler = this._register(new RunOnceScheduler(() => this.applyProjectionChanges(), 200)); this.projection.value.onUpdate(() => { if (!scheduler.isScheduled()) { scheduler.schedule(); From 7b707177921e2ee40ffcb277544673b16532806e Mon Sep 17 00:00:00 2001 From: Peng Lyu Date: Wed, 23 Aug 2023 15:13:21 -0700 Subject: [PATCH 150/221] Fix #190631. Emit outline change event. (#191135) --- .../notebook/browser/contrib/outline/notebookOutline.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/outline/notebookOutline.ts b/src/vs/workbench/contrib/notebook/browser/contrib/outline/notebookOutline.ts index 36a8c18f69b..cf6589b6027 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/outline/notebookOutline.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/outline/notebookOutline.ts @@ -208,6 +208,7 @@ export class NotebookCellOutline implements IOutline { } private _outlineProvider: NotebookCellOutlineProvider | undefined; + private _localDisposables = new DisposableStore(); constructor( private readonly _editor: INotebookEditorPane, @@ -221,9 +222,14 @@ export class NotebookCellOutline implements IOutline { if (!notebookEditor?.hasModel()) { this._outlineProvider?.dispose(); this._outlineProvider = undefined; + this._localDisposables.clear(); } else { this._outlineProvider?.dispose(); + this._localDisposables.clear(); this._outlineProvider = instantiationService.createInstance(NotebookCellOutlineProvider, notebookEditor, _target); + this._localDisposables.add(this._outlineProvider.onDidChange(e => { + this._onDidChange.fire(e); + })); } }; @@ -231,8 +237,6 @@ export class NotebookCellOutline implements IOutline { installSelectionListener(); })); - - installSelectionListener(); const treeDataSource: IDataSource = { getChildren: parent => parent instanceof NotebookCellOutline ? (this._outlineProvider?.entries ?? []) : parent.children }; const delegate = new NotebookOutlineVirtualDelegate(); @@ -315,6 +319,7 @@ export class NotebookCellOutline implements IOutline { this._dispoables.dispose(); this._entriesDisposables.dispose(); this._outlineProvider?.dispose(); + this._localDisposables.dispose(); } } From bf9604c5687aba630ec949738f4e683a042e6b0c Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Wed, 23 Aug 2023 15:15:07 -0700 Subject: [PATCH 151/221] Add event for when inlay hints are provided (#191134) --- .../src/languageFeatures/inlayHints.ts | 39 ++++++++++++++----- .../src/languageProvider.ts | 2 +- 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/extensions/typescript-language-features/src/languageFeatures/inlayHints.ts b/extensions/typescript-language-features/src/languageFeatures/inlayHints.ts index 1b9d554688d..4fa38e4986b 100644 --- a/extensions/typescript-language-features/src/languageFeatures/inlayHints.ts +++ b/extensions/typescript-language-features/src/languageFeatures/inlayHints.ts @@ -6,6 +6,7 @@ import * as vscode from 'vscode'; import { DocumentSelector } from '../configuration/documentSelector'; import { LanguageDescription } from '../configuration/languageDescription'; +import { TelemetryReporter } from '../logging/telemetry'; import { API } from '../tsServer/api'; import type * as Proto from '../tsServer/protocol/protocol'; import { Location, Position } from '../typeConverters'; @@ -29,13 +30,16 @@ class TypeScriptInlayHintsProvider extends Disposable implements vscode.InlayHin public static readonly minVersion = API.v440; - private readonly _onDidChangeInlayHints = new vscode.EventEmitter(); + private readonly _onDidChangeInlayHints = this._register(new vscode.EventEmitter()); public readonly onDidChangeInlayHints = this._onDidChangeInlayHints.event; + private hasReportedTelemetry = false; + constructor( private readonly language: LanguageDescription, private readonly client: ITypeScriptServiceClient, - private readonly fileConfigurationManager: FileConfigurationManager + private readonly fileConfigurationManager: FileConfigurationManager, + private readonly telemetryReporter: TelemetryReporter, ) { super(); @@ -54,31 +58,47 @@ class TypeScriptInlayHintsProvider extends Disposable implements vscode.InlayHin })); } - async provideInlayHints(model: vscode.TextDocument, range: vscode.Range, token: vscode.CancellationToken): Promise { + async provideInlayHints(model: vscode.TextDocument, range: vscode.Range, token: vscode.CancellationToken): Promise { const filepath = this.client.toOpenTsFilePath(model); if (!filepath) { - return []; + return; } if (!areInlayHintsEnabledForFile(this.language, model)) { - return []; + return; } const start = model.offsetAt(range.start); const length = model.offsetAt(range.end) - start; await this.fileConfigurationManager.ensureConfigurationForDocument(model, token); + if (token.isCancellationRequested) { + return; + } + + if (!this.hasReportedTelemetry) { + this.hasReportedTelemetry = true; + /* __GDPR__ + "inlayHints.provide" : { + "owner": "mjbvz", + "${include}": [ + "${TypeScriptCommonProperties}" + ] + } + */ + this.telemetryReporter.logTelemetry('inlayHints.provide', {}); + } const response = await this.client.execute('provideInlayHints', { file: filepath, start, length }, token); if (response.type !== 'response' || !response.success || !response.body) { - return []; + return; } return response.body.map(hint => { const result = new vscode.InlayHint( Position.fromLocation(hint.position), this.convertInlayHintText(hint), - hint.kind && fromProtocolInlayHintKind(hint.kind) + fromProtocolInlayHintKind(hint.kind) ); result.paddingLeft = hint.whitespaceBefore; result.paddingRight = hint.whitespaceAfter; @@ -127,13 +147,14 @@ export function register( selector: DocumentSelector, language: LanguageDescription, client: ITypeScriptServiceClient, - fileConfigurationManager: FileConfigurationManager + fileConfigurationManager: FileConfigurationManager, + telemetryReporter: TelemetryReporter, ) { return conditionalRegistration([ requireMinVersion(client, TypeScriptInlayHintsProvider.minVersion), requireSomeCapability(client, ClientCapability.Semantic), ], () => { - const provider = new TypeScriptInlayHintsProvider(language, client, fileConfigurationManager); + const provider = new TypeScriptInlayHintsProvider(language, client, fileConfigurationManager, telemetryReporter); return vscode.languages.registerInlayHintsProvider(selector.semantic, provider); }); } diff --git a/extensions/typescript-language-features/src/languageProvider.ts b/extensions/typescript-language-features/src/languageProvider.ts index 1de34c6998c..7acbf733f0c 100644 --- a/extensions/typescript-language-features/src/languageProvider.ts +++ b/extensions/typescript-language-features/src/languageProvider.ts @@ -74,7 +74,7 @@ export default class LanguageProvider extends Disposable { import('./languageFeatures/formatting').then(provider => this._register(provider.register(selector, this.description, this.client, this.fileConfigurationManager))), import('./languageFeatures/hover').then(provider => this._register(provider.register(selector, this.client, this.fileConfigurationManager))), import('./languageFeatures/implementations').then(provider => this._register(provider.register(selector, this.client))), - import('./languageFeatures/inlayHints').then(provider => this._register(provider.register(selector, this.description, this.client, this.fileConfigurationManager))), + import('./languageFeatures/inlayHints').then(provider => this._register(provider.register(selector, this.description, this.client, this.fileConfigurationManager, this.telemetryReporter))), import('./languageFeatures/jsDocCompletions').then(provider => this._register(provider.register(selector, this.description, this.client, this.fileConfigurationManager))), import('./languageFeatures/linkedEditing').then(provider => this._register(provider.register(selector, this.client))), import('./languageFeatures/organizeImports').then(provider => this._register(provider.register(selector, this.client, this.commandManager, this.fileConfigurationManager, this.telemetryReporter))), From 60c8cb0be41b6f666418564013d1e39ac26d514d Mon Sep 17 00:00:00 2001 From: rebornix Date: Wed, 23 Aug 2023 15:19:38 -0700 Subject: [PATCH 152/221] Re #183449. Roaming kernel history. --- .../notebookKernelHistoryServiceImpl.ts | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/services/notebookKernelHistoryServiceImpl.ts b/src/vs/workbench/contrib/notebook/browser/services/notebookKernelHistoryServiceImpl.ts index 7256ad1d404..0a19cda94bf 100644 --- a/src/vs/workbench/contrib/notebook/browser/services/notebookKernelHistoryServiceImpl.ts +++ b/src/vs/workbench/contrib/notebook/browser/services/notebookKernelHistoryServiceImpl.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Disposable } from 'vs/base/common/lifecycle'; +import { Disposable, DisposableStore } from 'vs/base/common/lifecycle'; import { LinkedMap, Touch } from 'vs/base/common/map'; import { localize } from 'vs/nls'; import { Categories } from 'vs/platform/action/common/actionCommonCategories'; @@ -36,6 +36,9 @@ export class NotebookKernelHistoryService extends Disposable implements INoteboo this._loadState(); this._register(this._storageService.onWillSaveState(() => this._saveState())); + this._register(this._storageService.onDidChangeValue(StorageScope.WORKSPACE, NotebookKernelHistoryService.STORAGE_KEY, this._register(new DisposableStore()))(() => { + this._restoreState(); + })); } getKernels(notebook: INotebookTextModelLike): { selected: INotebookKernel | undefined; all: INotebookKernel[] } { @@ -79,12 +82,28 @@ export class NotebookKernelHistoryService extends Disposable implements INoteboo if (notEmpty) { const serialized = this._serialize(); - this._storageService.store(NotebookKernelHistoryService.STORAGE_KEY, JSON.stringify(serialized), StorageScope.WORKSPACE, StorageTarget.MACHINE); + this._storageService.store(NotebookKernelHistoryService.STORAGE_KEY, JSON.stringify(serialized), StorageScope.WORKSPACE, StorageTarget.USER); } else { this._storageService.remove(NotebookKernelHistoryService.STORAGE_KEY, StorageScope.WORKSPACE); } } + private _restoreState(): void { + const serialized = this._storageService.get(NotebookKernelHistoryService.STORAGE_KEY, StorageScope.WORKSPACE); + if (serialized) { + try { + for (const [viewType, kernels] of JSON.parse(serialized)) { + const linkedMap = this._mostRecentKernelsMap[viewType] ?? new LinkedMap(); + for (const entry of kernels.entries) { + linkedMap.set(entry, entry, Touch.AsOld); + } + } + } catch (e) { + console.error('Deserialize notebook kernel history failed', e); + } + } + } + private _loadState(): void { const serialized = this._storageService.get(NotebookKernelHistoryService.STORAGE_KEY, StorageScope.WORKSPACE); if (serialized) { From e4a2928d14b38a67e334a120d447ded29e0f562c Mon Sep 17 00:00:00 2001 From: Tyler James Leonhardt Date: Wed, 23 Aug 2023 15:47:35 -0700 Subject: [PATCH 153/221] bump distro (#191139) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 584247e9fa4..2e5dcf01a2e 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.82.0", - "distro": "1591281180fd2cd18935e6847131d2d4213b7b69", + "distro": "56bfb9ce4a8d2298f475a1b8d9c7a7b5a72204f2", "author": { "name": "Microsoft Corporation" }, From b82a7222adc865e8a27b1b14c1fd11ab2900f23e Mon Sep 17 00:00:00 2001 From: Joyce Er Date: Wed, 23 Aug 2023 15:49:45 -0700 Subject: [PATCH 154/221] Fix chat response file tree border radius (#191142) --- .../workbench/contrib/chat/browser/chatListRenderer.css | 8 -------- src/vs/workbench/contrib/chat/browser/media/chat.css | 8 ++++++-- 2 files changed, 6 insertions(+), 10 deletions(-) delete mode 100644 src/vs/workbench/contrib/chat/browser/chatListRenderer.css diff --git a/src/vs/workbench/contrib/chat/browser/chatListRenderer.css b/src/vs/workbench/contrib/chat/browser/chatListRenderer.css deleted file mode 100644 index 49c3ab7833c..00000000000 --- a/src/vs/workbench/contrib/chat/browser/chatListRenderer.css +++ /dev/null @@ -1,8 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -.interactive-response-progress-tree .monaco-tl-row:hover { - background-color: var(--vscode-list-hoverBackground); -} diff --git a/src/vs/workbench/contrib/chat/browser/media/chat.css b/src/vs/workbench/contrib/chat/browser/media/chat.css index ab5e3bd6c59..33b798459ea 100644 --- a/src/vs/workbench/contrib/chat/browser/media/chat.css +++ b/src/vs/workbench/contrib/chat/browser/media/chat.css @@ -436,8 +436,6 @@ .interactive-response-progress-tree { margin: 16px 0px; - border-radius: 4px; - border: 1px solid var(--vscode-input-border, transparent); } .interactive-response-progress-tree.focused { @@ -458,3 +456,9 @@ align-items: start; gap: 6px; } + +.interactive-response-progress-tree .monaco-list .monaco-scrollable-element .monaco-list-rows { + border: 1px solid var(--vscode-input-border,transparent); + border-radius: 4px; + width: auto; +} From 9a69c2ab7ca5e81f513a00179b717a8b9bc2217a Mon Sep 17 00:00:00 2001 From: Tyler James Leonhardt Date: Wed, 23 Aug 2023 16:03:45 -0700 Subject: [PATCH 155/221] One Provider per Type (#191136) Simpler design due to feedback from Logan. --- .../browser/mainThreadAiRelatedInformation.ts | 11 ++++--- .../workbench/api/common/extHost.api.impl.ts | 4 +-- .../workbench/api/common/extHost.protocol.ts | 4 +-- .../api/common/extHostAiRelatedInformation.ts | 11 ++++--- .../common/aiRelatedInformation.ts | 12 ++++---- .../common/aiRelatedInformationService.ts | 29 +++++++++---------- .../vscode.proposed.aiRelatedInformation.d.ts | 27 +++++------------ 7 files changed, 41 insertions(+), 57 deletions(-) diff --git a/src/vs/workbench/api/browser/mainThreadAiRelatedInformation.ts b/src/vs/workbench/api/browser/mainThreadAiRelatedInformation.ts index b198f41be47..e254b5f4149 100644 --- a/src/vs/workbench/api/browser/mainThreadAiRelatedInformation.ts +++ b/src/vs/workbench/api/browser/mainThreadAiRelatedInformation.ts @@ -7,9 +7,8 @@ import { CancellationToken } from 'vs/base/common/cancellation'; import { Disposable, DisposableMap } from 'vs/base/common/lifecycle'; import { ExtHostAiRelatedInformationShape, ExtHostContext, MainContext, MainThreadAiRelatedInformationShape } from 'vs/workbench/api/common/extHost.protocol'; import { RelatedInformationType } from 'vs/workbench/api/common/extHostTypes'; -import { IAiRelatedInformationProvider, IAiRelatedInformationService } from 'vs/workbench/services/aiRelatedInformation/common/aiRelatedInformation'; +import { IAiRelatedInformationProvider, IAiRelatedInformationService, RelatedInformationResult } from 'vs/workbench/services/aiRelatedInformation/common/aiRelatedInformation'; import { IExtHostContext, extHostNamedCustomer } from 'vs/workbench/services/extensions/common/extHostCustomers'; -import { RelatedInformationResult } from 'vscode'; @extHostNamedCustomer(MainContext.MainThreadAiRelatedInformation) export class MainThreadAiRelatedInformation extends Disposable implements MainThreadAiRelatedInformationShape { @@ -29,13 +28,13 @@ export class MainThreadAiRelatedInformation extends Disposable implements MainTh return this._aiRelatedInformationService.getRelatedInformation(query, types, CancellationToken.None); } - $registerAiRelatedInformationProvider(handle: number, types: RelatedInformationType[]): void { + $registerAiRelatedInformationProvider(handle: number, type: RelatedInformationType): void { const provider: IAiRelatedInformationProvider = { - provideAiRelatedInformation: (query, types, token) => { - return this._proxy.$provideAiRelatedInformation(handle, query, types, token); + provideAiRelatedInformation: (query, token) => { + return this._proxy.$provideAiRelatedInformation(handle, query, token); }, }; - this._registrations.set(handle, this._aiRelatedInformationService.registerAiRelatedInformationProvider(types, provider)); + this._registrations.set(handle, this._aiRelatedInformationService.registerAiRelatedInformationProvider(type, provider)); } $unregisterAiRelatedInformationProvider(handle: number): void { diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index f9803e1476f..acdb35b1b1e 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -1332,9 +1332,9 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I checkProposedApiEnabled(extension, 'aiRelatedInformation'); return extHostAiRelatedInformation.getRelatedInformation(extension, query, types); }, - registerRelatedInformationProvider(types: vscode.RelatedInformationType[], provider: vscode.RelatedInformationProvider) { + registerRelatedInformationProvider(type: vscode.RelatedInformationType, provider: vscode.RelatedInformationProvider) { checkProposedApiEnabled(extension, 'aiRelatedInformation'); - return extHostAiRelatedInformation.registerRelatedInformationProvider(extension, types, provider); + return extHostAiRelatedInformation.registerRelatedInformationProvider(extension, type, provider); }, registerEmbeddingVectorProvider(model: string, provider: vscode.EmbeddingVectorProvider) { checkProposedApiEnabled(extension, 'aiRelatedInformation'); diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index 93826ca0f5f..37e0b6c9ba9 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -1675,12 +1675,12 @@ export interface MainThreadSemanticSimilarityShape extends IDisposable { } export interface ExtHostAiRelatedInformationShape { - $provideAiRelatedInformation(handle: number, query: string, types: RelatedInformationType[], token: CancellationToken): Promise; + $provideAiRelatedInformation(handle: number, query: string, token: CancellationToken): Promise; } export interface MainThreadAiRelatedInformationShape { $getAiRelatedInformation(query: string, types: RelatedInformationType[]): Promise; - $registerAiRelatedInformationProvider(handle: number, types: RelatedInformationType[]): void; + $registerAiRelatedInformationProvider(handle: number, type: RelatedInformationType): void; $unregisterAiRelatedInformationProvider(handle: number): void; } diff --git a/src/vs/workbench/api/common/extHostAiRelatedInformation.ts b/src/vs/workbench/api/common/extHostAiRelatedInformation.ts index 9dc39e42ae1..4cb934e1b1e 100644 --- a/src/vs/workbench/api/common/extHostAiRelatedInformation.ts +++ b/src/vs/workbench/api/common/extHostAiRelatedInformation.ts @@ -5,7 +5,7 @@ import { IExtensionDescription } from 'vs/platform/extensions/common/extensions'; import { ExtHostAiRelatedInformationShape, IMainContext, MainContext, MainThreadAiRelatedInformationShape } from 'vs/workbench/api/common/extHost.protocol'; -import type { CancellationToken, RelatedInformationProvider, RelatedInformationResult, RelatedInformationType } from 'vscode'; +import type { CancellationToken, RelatedInformationProvider, RelatedInformationType, RelatedInformationResult } from 'vscode'; import { Disposable } from 'vs/workbench/api/common/extHostTypes'; export class ExtHostRelatedInformation implements ExtHostAiRelatedInformationShape { @@ -18,7 +18,7 @@ export class ExtHostRelatedInformation implements ExtHostAiRelatedInformationSha this._proxy = mainContext.getProxy(MainContext.MainThreadAiRelatedInformation); } - async $provideAiRelatedInformation(handle: number, query: string, types: RelatedInformationType[], token: CancellationToken): Promise { + async $provideAiRelatedInformation(handle: number, query: string, token: CancellationToken): Promise { if (this._relatedInformationProviders.size === 0) { throw new Error('No semantic similarity providers registered'); } @@ -28,8 +28,7 @@ export class ExtHostRelatedInformation implements ExtHostAiRelatedInformationSha throw new Error('Semantic similarity provider not found'); } - // TODO: should this return undefined or an empty array? - const result = await provider.provideRelatedInformation(query, types, token) ?? []; + const result = await provider.provideRelatedInformation(query, token) ?? []; return result; } @@ -37,11 +36,11 @@ export class ExtHostRelatedInformation implements ExtHostAiRelatedInformationSha return this._proxy.$getAiRelatedInformation(query, types); } - registerRelatedInformationProvider(extension: IExtensionDescription, types: RelatedInformationType[], provider: RelatedInformationProvider): Disposable { + registerRelatedInformationProvider(extension: IExtensionDescription, type: RelatedInformationType, provider: RelatedInformationProvider): Disposable { const handle = this._nextHandle; this._nextHandle++; this._relatedInformationProviders.set(handle, provider); - this._proxy.$registerAiRelatedInformationProvider(handle, types); + this._proxy.$registerAiRelatedInformationProvider(handle, type); return new Disposable(() => { this._proxy.$unregisterAiRelatedInformationProvider(handle); this._relatedInformationProviders.delete(handle); diff --git a/src/vs/workbench/services/aiRelatedInformation/common/aiRelatedInformation.ts b/src/vs/workbench/services/aiRelatedInformation/common/aiRelatedInformation.ts index a8bddf2c1e4..f3b7d9a090f 100644 --- a/src/vs/workbench/services/aiRelatedInformation/common/aiRelatedInformation.ts +++ b/src/vs/workbench/services/aiRelatedInformation/common/aiRelatedInformation.ts @@ -16,29 +16,31 @@ export enum RelatedInformationType { SettingInformation = 4 } -export interface RelatedInformationResult { +interface RelatedInformationBaseResult { type: RelatedInformationType; weight: number; } -export interface CommandInformationResult extends RelatedInformationResult { +export interface CommandInformationResult extends RelatedInformationBaseResult { type: RelatedInformationType.CommandInformation; command: string; } -export interface SettingInformationResult extends RelatedInformationResult { +export interface SettingInformationResult extends RelatedInformationBaseResult { type: RelatedInformationType.SettingInformation; setting: string; } +export type RelatedInformationResult = CommandInformationResult | SettingInformationResult; + export interface IAiRelatedInformationService { readonly _serviceBrand: undefined; isEnabled(): boolean; getRelatedInformation(query: string, types: RelatedInformationType[], token: CancellationToken): Promise; - registerAiRelatedInformationProvider(types: RelatedInformationType[], provider: IAiRelatedInformationProvider): IDisposable; + registerAiRelatedInformationProvider(type: RelatedInformationType, provider: IAiRelatedInformationProvider): IDisposable; } export interface IAiRelatedInformationProvider { - provideAiRelatedInformation(query: string, types: RelatedInformationType[], token: CancellationToken): Promise; + provideAiRelatedInformation(query: string, token: CancellationToken): Promise; } diff --git a/src/vs/workbench/services/aiRelatedInformation/common/aiRelatedInformationService.ts b/src/vs/workbench/services/aiRelatedInformation/common/aiRelatedInformationService.ts index e0309ff37d1..7168c3b4eed 100644 --- a/src/vs/workbench/services/aiRelatedInformation/common/aiRelatedInformationService.ts +++ b/src/vs/workbench/services/aiRelatedInformation/common/aiRelatedInformationService.ts @@ -24,24 +24,21 @@ export class AiRelatedInformationService implements IAiRelatedInformationService return this._providers.size > 0; } - registerAiRelatedInformationProvider(types: RelatedInformationType[], provider: IAiRelatedInformationProvider): IDisposable { - for (const type of types) { - const providers = this._providers.get(type) ?? []; - providers.push(provider); - this._providers.set(type, providers); - } + registerAiRelatedInformationProvider(type: RelatedInformationType, provider: IAiRelatedInformationProvider): IDisposable { + const providers = this._providers.get(type) ?? []; + providers.push(provider); + this._providers.set(type, providers); + return { dispose: () => { - for (const type of types) { - const providers = this._providers.get(type) ?? []; - const index = providers.indexOf(provider); - if (index !== -1) { - providers.splice(index, 1); - } - if (providers.length === 0) { - this._providers.delete(type); - } + const providers = this._providers.get(type) ?? []; + const index = providers.indexOf(provider); + if (index !== -1) { + providers.splice(index, 1); + } + if (providers.length === 0) { + this._providers.delete(type); } } }; @@ -78,7 +75,7 @@ export class AiRelatedInformationService implements IAiRelatedInformationService for (const provider of providers) { cancellablePromises.push(createCancelablePromise(async t => { try { - const result = await provider.provideAiRelatedInformation(query, types, t); + const result = await provider.provideAiRelatedInformation(query, t); // double filter just in case return result.filter(r => types.includes(r.type)); } catch (e) { diff --git a/src/vscode-dts/vscode.proposed.aiRelatedInformation.d.ts b/src/vscode-dts/vscode.proposed.aiRelatedInformation.d.ts index d3916c50608..e5e28653cec 100644 --- a/src/vscode-dts/vscode.proposed.aiRelatedInformation.d.ts +++ b/src/vscode-dts/vscode.proposed.aiRelatedInformation.d.ts @@ -7,13 +7,6 @@ declare module 'vscode' { // https://github.com/microsoft/vscode/issues/190909 - export interface SearchResult { - // from Andrea - preview: string; - resource: Uri; - location: Range; - } - export enum RelatedInformationType { SymbolInformation = 1, CommandInformation = 2, @@ -21,33 +14,27 @@ declare module 'vscode' { SettingInformation = 4 } - export interface RelatedInformationResult { + interface RelatedInformationBaseResult { type: RelatedInformationType; weight: number; } - export interface SymbolInformationResult extends RelatedInformationResult { - type: RelatedInformationType.SymbolInformation; - symbolInformation: SymbolInformation; - } + // TODO: Symbols and Search - export interface CommandInformationResult extends RelatedInformationResult { + export interface CommandInformationResult extends RelatedInformationBaseResult { type: RelatedInformationType.CommandInformation; command: string; } - export interface SettingInformationResult extends RelatedInformationResult { + export interface SettingInformationResult extends RelatedInformationBaseResult { type: RelatedInformationType.SettingInformation; setting: string; } - export interface SearchInformationResult extends RelatedInformationResult { - type: RelatedInformationType.SearchInformation; - searchResult: SearchResult; - } + export type RelatedInformationResult = CommandInformationResult | SettingInformationResult; export interface RelatedInformationProvider { - provideRelatedInformation(query: string, types: RelatedInformationType[], token: CancellationToken): ProviderResult; + provideRelatedInformation(query: string, token: CancellationToken): ProviderResult; } export interface EmbeddingVectorProvider { @@ -56,7 +43,7 @@ declare module 'vscode' { export namespace ai { export function getRelatedInformation(query: string, types: RelatedInformationType[], token: CancellationToken): Thenable; - export function registerRelatedInformationProvider(types: RelatedInformationType[], provider: RelatedInformationProvider): Disposable; + export function registerRelatedInformationProvider(type: RelatedInformationType, provider: RelatedInformationProvider): Disposable; export function registerEmbeddingVectorProvider(model: string, provider: EmbeddingVectorProvider): Disposable; } } From ba35c622b06307173c04184e0e270673d750a4d2 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Wed, 23 Aug 2023 16:26:51 -0700 Subject: [PATCH 156/221] Allow InteractiveProgressContent to return a markdown string (#191145) This allows enabling of specific command uris in responses --- src/vs/workbench/api/browser/mainThreadChat.ts | 7 ++++--- .../workbench/api/common/extHost.protocol.ts | 2 +- src/vs/workbench/api/common/extHostChat.ts | 4 ++++ .../contrib/chat/browser/chatListRenderer.ts | 9 +++++---- .../workbench/contrib/chat/common/chatModel.ts | 18 +++++++++++------- .../contrib/chat/common/chatService.ts | 2 +- .../contrib/chat/common/chatServiceImpl.ts | 2 +- .../vscode.proposed.interactive.d.ts | 2 +- 8 files changed, 28 insertions(+), 18 deletions(-) diff --git a/src/vs/workbench/api/browser/mainThreadChat.ts b/src/vs/workbench/api/browser/mainThreadChat.ts index ddeba6f997b..6b45f162796 100644 --- a/src/vs/workbench/api/browser/mainThreadChat.ts +++ b/src/vs/workbench/api/browser/mainThreadChat.ts @@ -5,6 +5,7 @@ import { DeferredPromise } from 'vs/base/common/async'; import { Emitter } from 'vs/base/common/event'; +import { IMarkdownString } from 'vs/base/common/htmlContent'; import { Disposable, DisposableMap } from 'vs/base/common/lifecycle'; import { revive } from 'vs/base/common/marshalling'; import { URI, UriComponents } from 'vs/base/common/uri'; @@ -19,13 +20,13 @@ import { IExtHostContext, extHostNamedCustomer } from 'vs/workbench/services/ext export class MainThreadChat extends Disposable implements MainThreadChatShape { private readonly _providerRegistrations = this._register(new DisposableMap()); - private readonly _activeRequestProgressCallbacks = new Map (DeferredPromise | void)>(); + private readonly _activeRequestProgressCallbacks = new Map (DeferredPromise | void)>(); private readonly _stateEmitters = new Map>(); private readonly _proxy: ExtHostChatShape; private _responsePartHandlePool = 0; - private readonly _activeResponsePartPromises = new Map>(); + private readonly _activeResponsePartPromises = new Map>(); constructor( extHostContext: IExtHostContext, @@ -134,7 +135,7 @@ export class MainThreadChat extends Disposable implements MainThreadChatShape { if ('placeholder' in progress) { const responsePartId = `${id}_${++this._responsePartHandlePool}`; - const deferredContentPromise = new DeferredPromise(); + const deferredContentPromise = new DeferredPromise(); this._activeResponsePartPromises.set(responsePartId, deferredContentPromise); this._activeRequestProgressCallbacks.get(id)?.({ ...progress, resolvedContent: deferredContentPromise.p }); return this._responsePartHandlePool; diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index 37e0b6c9ba9..e4964fb5670 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -1216,7 +1216,7 @@ export interface IChatResponseProgressFileTreeData { children?: IChatResponseProgressFileTreeData[]; } -export type IChatResponseProgressDto = { content: string } | { requestId: string } | { placeholder: string } | { treeData: IChatResponseProgressFileTreeData }; +export type IChatResponseProgressDto = { content: string | IMarkdownString } | { requestId: string } | { placeholder: string } | { treeData: IChatResponseProgressFileTreeData }; export interface MainThreadChatShape extends IDisposable { $registerChatProvider(handle: number, id: string): Promise; diff --git a/src/vs/workbench/api/common/extHostChat.ts b/src/vs/workbench/api/common/extHostChat.ts index db4f90727ba..9aa2c625cc9 100644 --- a/src/vs/workbench/api/common/extHostChat.ts +++ b/src/vs/workbench/api/common/extHostChat.ts @@ -232,6 +232,10 @@ export class ExtHostChat implements ExtHostChatShape { const [progressHandle, progressContent] = res; this._proxy.$acceptResponseProgress(handle, sessionId, progressContent, progressHandle ?? undefined); }); + } else if ('content' in progress) { + this._proxy.$acceptResponseProgress(handle, sessionId, { + content: typeof progress.content === 'string' ? progress.content : typeConvert.MarkdownString.from(progress.content) + }); } else { this._proxy.$acceptResponseProgress(handle, sessionId, progress); } diff --git a/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts b/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts index dad24e99b60..e6ec6bd3ae8 100644 --- a/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts +++ b/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts @@ -316,12 +316,12 @@ export class ChatListItemRenderer extends Disposable implements ITreeRenderer, element: ChatTreeItem, index: number, templateData: IChatListItemTemplate) { const fillInIncompleteTokens = isResponseVM(element) && (!element.isComplete || element.isCanceled || element.errorDetails?.responseIsFiltered || element.errorDetails?.responseIsIncomplete); dom.clearNode(templateData.value); let fileTreeIndex = 0; - for (const data of markdownValue) { + for (const data of value) { const result = 'value' in data ? this.renderMarkdown(data, element, templateData.elementDisposables, templateData, fillInIncompleteTokens) : this.renderTreeData(data, element, templateData.elementDisposables, templateData, fileTreeIndex++); @@ -577,8 +577,9 @@ export class ChatListItemRenderer extends Disposable implements ITreeRenderer; - updateContent(responsePart: string | { treeData: IChatResponseProgressFileTreeData } | { placeholder: string; resolvedContent?: Promise }, quiet?: boolean): void; + updateContent(responsePart: string | IMarkdownString | { treeData: IChatResponseProgressFileTreeData } | { placeholder: string; resolvedContent?: Promise }, quiet?: boolean): void; asString(): string; } @@ -125,17 +125,21 @@ export class Response implements IResponse { return this._responseRepr; } - updateContent(responsePart: string | { treeData: IChatResponseProgressFileTreeData } | { placeholder: string; resolvedContent?: Promise }, quiet?: boolean): void { - if (typeof responsePart === 'string') { + updateContent(responsePart: string | IMarkdownString | { treeData: IChatResponseProgressFileTreeData } | { placeholder: string; resolvedContent?: Promise }, quiet?: boolean): void { + if (typeof responsePart === 'string' || isMarkdownString(responsePart)) { const responsePartLength = this._responseParts.length - 1; const lastResponsePart = this._responseParts[responsePartLength]; if (lastResponsePart.isPlaceholder === true || isCompleteInteractiveProgressTreeData(lastResponsePart)) { // The last part is resolving or a tree data item, start a new part - this._responseParts.push({ string: new MarkdownString(responsePart) }); + this._responseParts.push({ string: typeof responsePart === 'string' ? new MarkdownString(responsePart) : responsePart }); } else { // Combine this part with the last, non-resolving string part - this._responseParts[responsePartLength] = { string: new MarkdownString(lastResponsePart.string.value + responsePart) }; + if (isMarkdownString(responsePart)) { + this._responseParts[responsePartLength] = { string: new MarkdownString(lastResponsePart.string.value + responsePart.value, responsePart) }; + } else { + this._responseParts[responsePartLength] = { string: new MarkdownString(lastResponsePart.string.value + responsePart, lastResponsePart.string) }; + } } this._updateRepr(quiet); @@ -250,7 +254,7 @@ export class ChatResponseModel extends Disposable implements IChatResponseModel this._id = 'response_' + ChatResponseModel.nextId++; } - updateContent(responsePart: string | { treeData: IChatResponseProgressFileTreeData } | { placeholder: string; resolvedContent?: Promise }, quiet?: boolean) { + updateContent(responsePart: string | IMarkdownString | { treeData: IChatResponseProgressFileTreeData } | { placeholder: string; resolvedContent?: Promise }, quiet?: boolean) { this._response.updateContent(responsePart, quiet); } diff --git a/src/vs/workbench/contrib/chat/common/chatService.ts b/src/vs/workbench/contrib/chat/common/chatService.ts index 2812120dccd..9039dfb5150 100644 --- a/src/vs/workbench/contrib/chat/common/chatService.ts +++ b/src/vs/workbench/contrib/chat/common/chatService.ts @@ -52,7 +52,7 @@ export interface IChatResponseProgressFileTreeData { } export type IChatProgress = - { content: string } | { requestId: string } | { treeData: IChatResponseProgressFileTreeData } | { placeholder: string; resolvedContent: Promise }; + { content: string | IMarkdownString } | { requestId: string } | { treeData: IChatResponseProgressFileTreeData } | { placeholder: string; resolvedContent: Promise }; export interface IPersistedChatState { } export interface IChatProvider { diff --git a/src/vs/workbench/contrib/chat/common/chatServiceImpl.ts b/src/vs/workbench/contrib/chat/common/chatServiceImpl.ts index ae621f87f69..bd759fd4c94 100644 --- a/src/vs/workbench/contrib/chat/common/chatServiceImpl.ts +++ b/src/vs/workbench/contrib/chat/common/chatServiceImpl.ts @@ -450,7 +450,7 @@ export class ChatService extends Disposable implements IChatService { gotProgress = true; if ('content' in progress) { - this.trace('sendRequest', `Provider returned progress for session ${model.sessionId}, ${progress.content.length} chars`); + this.trace('sendRequest', `Provider returned progress for session ${model.sessionId}, ${typeof progress.content === 'string' ? progress.content.length : progress.content.value.length} chars`); } else if ('placeholder' in progress) { this.trace('sendRequest', `Provider returned placeholder for session ${model.sessionId}, ${progress.placeholder}`); } else if (isCompleteInteractiveProgressTreeData(progress)) { diff --git a/src/vscode-dts/vscode.proposed.interactive.d.ts b/src/vscode-dts/vscode.proposed.interactive.d.ts index 382afeb8277..8ec16060be1 100644 --- a/src/vscode-dts/vscode.proposed.interactive.d.ts +++ b/src/vscode-dts/vscode.proposed.interactive.d.ts @@ -121,7 +121,7 @@ declare module 'vscode' { } export interface InteractiveProgressContent { - content: string; + content: string | MarkdownString; } export interface InteractiveProgressId { From f7a7d9488fe56fba0851a9f53ab203a5136a799c Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Wed, 23 Aug 2023 16:47:31 -0700 Subject: [PATCH 157/221] cli: serve-web listener improvements (#191146) - Allow listening on a socket path (required manually implementing the Accept trait), fixes #191043 - Parse the host syntax correctly, fixes #191067 --- cli/src/async_pipe.rs | 55 ++++++++++++++++++++++++++++++- cli/src/commands/args.rs | 3 ++ cli/src/commands/serve_web.rs | 62 +++++++++++++++++++++-------------- 3 files changed, 94 insertions(+), 26 deletions(-) diff --git a/cli/src/async_pipe.rs b/cli/src/async_pipe.rs index 6c7c918967a..e9b710c1d68 100644 --- a/cli/src/async_pipe.rs +++ b/cli/src/async_pipe.rs @@ -6,6 +6,8 @@ use crate::{constants::APPLICATION_NAME, util::errors::CodeError}; use async_trait::async_trait; use std::path::{Path, PathBuf}; +use std::pin::Pin; +use std::task::{Context, Poll}; use tokio::io::{AsyncRead, AsyncWrite}; use tokio::net::TcpListener; use uuid::Uuid; @@ -44,7 +46,7 @@ cfg_if::cfg_if! { } else { use tokio::{time::sleep, io::ReadBuf}; use tokio::net::windows::named_pipe::{ClientOptions, ServerOptions, NamedPipeClient, NamedPipeServer}; - use std::{time::Duration, pin::Pin, task::{Context, Poll}, io}; + use std::{time::Duration, io}; use pin_project::pin_project; #[pin_project(project = AsyncPipeProj)] @@ -174,6 +176,57 @@ cfg_if::cfg_if! { } } +impl AsyncPipeListener { + pub fn into_pollable(self) -> PollableAsyncListener { + PollableAsyncListener { + listener: Some(self), + write_fut: tokio_util::sync::ReusableBoxFuture::new(make_accept_fut(None)), + } + } +} + +pub struct PollableAsyncListener { + listener: Option, + write_fut: tokio_util::sync::ReusableBoxFuture< + 'static, + (AsyncPipeListener, Result), + >, +} + +async fn make_accept_fut( + data: Option, +) -> (AsyncPipeListener, Result) { + match data { + Some(mut l) => { + let c = l.accept().await; + (l, c) + } + None => unreachable!("this future should not be pollable in this state"), + } +} + +impl hyper::server::accept::Accept for PollableAsyncListener { + type Conn = AsyncPipe; + type Error = CodeError; + + fn poll_accept( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll>> { + if let Some(l) = self.listener.take() { + self.write_fut.set(make_accept_fut(Some(l))) + } + + match self.write_fut.poll(cx) { + Poll::Ready((l, cnx)) => { + self.listener = Some(l); + Poll::Ready(Some(cnx)) + } + Poll::Pending => Poll::Pending, + } + } +} + /// Gets a random name for a pipe/socket on the paltform pub fn get_socket_name() -> PathBuf { cfg_if::cfg_if! { diff --git a/cli/src/commands/args.rs b/cli/src/commands/args.rs index cce01c52fd9..bfa1c6f2da4 100644 --- a/cli/src/commands/args.rs +++ b/cli/src/commands/args.rs @@ -185,6 +185,9 @@ pub struct ServeWebArgs { /// Host to listen on, defaults to 'localhost' #[clap(long)] pub host: Option, + // The path to a socket file for the server to listen to. + #[clap(long)] + pub socket_path: Option, /// Port to listen on. If 0 is passed a random free port is picked. #[clap(long, default_value_t = 8000)] pub port: u16, diff --git a/cli/src/commands/serve_web.rs b/cli/src/commands/serve_web.rs index b2bf4d431e4..4a3af432444 100644 --- a/cli/src/commands/serve_web.rs +++ b/cli/src/commands/serve_web.rs @@ -16,7 +16,9 @@ use tokio::io::{AsyncBufReadExt, BufReader}; use tokio::pin; use tokio::process::Command; -use crate::async_pipe::{get_socket_name, get_socket_rw_stream, AsyncPipe}; +use crate::async_pipe::{ + get_socket_name, get_socket_rw_stream, listen_socket_rw_stream, AsyncPipe, +}; use crate::constants::VSCODE_CLI_QUALITY; use crate::download_cache::DownloadCache; use crate::log; @@ -53,43 +55,53 @@ const RELEASE_CACHE_SECS: u64 = 60 * 60; /// while new clients get new VS Code Server versions. pub async fn serve_web(ctx: CommandContext, mut args: ServeWebArgs) -> Result { legal::require_consent(&ctx.paths, args.accept_server_license_terms)?; - let mut addr: SocketAddr = match &args.host { - Some(h) => h.parse().map_err(CodeError::InvalidHostAddress)?, - None => SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 0), - }; - addr.set_port(args.port); let platform: crate::update_service::Platform = PreReqChecker::new().verify().await?; if !args.without_connection_token { // Ensure there's a defined connection token, since if multiple server versions // are excuted, they will need to have a single shared token. - let connection_token = args - .connection_token - .clone() - .unwrap_or_else(|| uuid::Uuid::new_v4().to_string()); - ctx.log.result(format!( - "Web UI available at http://{}?tkn={}", - addr, connection_token, - )); - args.connection_token = Some(connection_token); - } else { - ctx.log - .result(format!("Web UI available at http://{}", addr)); - args.connection_token = None; + args.connection_token = Some( + args.connection_token + .clone() + .unwrap_or_else(|| uuid::Uuid::new_v4().to_string()), + ); } - let cm = ConnectionManager::new(&ctx, platform, args); - let make_svc = make_service_fn(move |_conn| { + let cm = ConnectionManager::new(&ctx, platform, args.clone()); + let make_svc = move || { let cm = cm.clone(); - let log = ctx.log.clone(); + let log = cm.log.clone(); let service = service_fn(move |req| handle(cm.clone(), log.clone(), req)); async move { Ok::<_, Infallible>(service) } - }); + }; - let server = Server::bind(&addr).serve(make_svc); + let r = if let Some(s) = args.socket_path { + let socket = listen_socket_rw_stream(&PathBuf::from(&s)).await?; + ctx.log.result(format!("Web UI available on {}", s)); + Server::builder(socket.into_pollable()) + .serve(make_service_fn(|_| make_svc())) + .await + } else { + let addr: SocketAddr = match &args.host { + Some(h) => { + SocketAddr::new(h.parse().map_err(CodeError::InvalidHostAddress)?, args.port) + } + None => SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), args.port), + }; - server.await.map_err(CodeError::CouldNotListenOnInterface)?; + let mut listening = format!("Web UI available at http://{}", addr); + if let Some(ct) = args.connection_token { + listening.push_str(&format!("?tkn={}", ct)); + } + ctx.log.result(listening); + + Server::bind(&addr) + .serve(make_service_fn(|_| make_svc())) + .await + }; + + r.map_err(CodeError::CouldNotListenOnInterface)?; Ok(0) } From e23be75182cabbf88bb2662d55c5c34c1f9a50f4 Mon Sep 17 00:00:00 2001 From: Ole Date: Thu, 24 Aug 2023 01:55:41 +0200 Subject: [PATCH 158/221] Increase shortcut consistency of web with electron. (#191061) On electron, nothing changes. On web, * "Focus Application Menu" changes from F10 to Alt+F10 (this action only exists on web) * "Debugger: Step over" changes from Alt+F10 to F10 like on electron While #183510 already added the F10 binding for the debugger also on web, it did not actually have any effect, because of a conflict with F10 for "Focus Application Menu" on web. This change was agreed upon in #190180 due to the relatively low usage of "Open Application Menu" in the interest of more overall consistency. Fixes #190180. --- src/vs/workbench/browser/parts/titlebar/menubarControl.ts | 4 ++-- src/vs/workbench/contrib/debug/browser/debugCommands.ts | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/browser/parts/titlebar/menubarControl.ts b/src/vs/workbench/browser/parts/titlebar/menubarControl.ts index e96e773a916..ec47bd48bca 100644 --- a/src/vs/workbench/browser/parts/titlebar/menubarControl.ts +++ b/src/vs/workbench/browser/parts/titlebar/menubarControl.ts @@ -32,7 +32,7 @@ import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/la import { isFullscreen } from 'vs/base/browser/browser'; import { IHostService } from 'vs/workbench/services/host/browser/host'; import { BrowserFeatures } from 'vs/base/browser/canIUse'; -import { KeyCode } from 'vs/base/common/keyCodes'; +import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { IsMacNativeContext, IsWebContext } from 'vs/platform/contextkey/common/contextkeys'; import { ICommandService } from 'vs/platform/commands/common/commands'; @@ -440,7 +440,7 @@ export class CustomMenubarControl extends MenubarControl { id: `workbench.actions.menubar.focus`, title: { value: localize('focusMenu', "Focus Application Menu"), original: 'Focus Application Menu' }, keybinding: { - primary: KeyCode.F10, + primary: KeyMod.Alt | KeyCode.F10, weight: KeybindingWeight.WorkbenchContrib, when: IsWebContext }, diff --git a/src/vs/workbench/contrib/debug/browser/debugCommands.ts b/src/vs/workbench/contrib/debug/browser/debugCommands.ts index 9515ab1ad73..1fecc75d4f9 100644 --- a/src/vs/workbench/contrib/debug/browser/debugCommands.ts +++ b/src/vs/workbench/contrib/debug/browser/debugCommands.ts @@ -474,7 +474,6 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({ id: STEP_OVER_ID, weight: KeybindingWeight.WorkbenchContrib, primary: KeyCode.F10, - secondary: isWeb ? [(KeyMod.Alt | KeyCode.F10)] : undefined, // Keep Alt-F10 for web for backwards-compatibility when: CONTEXT_DEBUG_STATE.isEqualTo('stopped'), handler: async (accessor: ServicesAccessor, _: string, context: CallStackContext | unknown) => { const contextKeyService = accessor.get(IContextKeyService); From a0377f0c51dbb2d3188565cdf35e89929f864e65 Mon Sep 17 00:00:00 2001 From: Peng Lyu Date: Wed, 23 Aug 2023 20:42:18 -0700 Subject: [PATCH 159/221] Fix #189809. Update tree options paddingBottom. (#191143) --- src/vs/base/browser/ui/tree/abstractTree.ts | 2 +- src/vs/platform/list/browser/listService.ts | 4 ++-- src/vs/workbench/contrib/files/browser/views/explorerView.ts | 2 +- src/vs/workbench/contrib/search/browser/searchView.ts | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/vs/base/browser/ui/tree/abstractTree.ts b/src/vs/base/browser/ui/tree/abstractTree.ts index 3591193bab9..70199a8164c 100644 --- a/src/vs/base/browser/ui/tree/abstractTree.ts +++ b/src/vs/base/browser/ui/tree/abstractTree.ts @@ -1218,7 +1218,7 @@ export interface IAbstractTreeOptions extends IAbstractTr readonly collapseByDefault?: boolean; // defaults to false readonly filter?: ITreeFilter; readonly dnd?: ITreeDragAndDrop; - readonly additionalScrollHeight?: number; + readonly paddingBottom?: number; readonly findWidgetEnabled?: boolean; readonly findWidgetStyles?: IFindWidgetStyles; readonly defaultFindVisibility?: TreeVisibility | ((e: T) => TreeVisibility); diff --git a/src/vs/platform/list/browser/listService.ts b/src/vs/platform/list/browser/listService.ts index 7c5a1eb9cd6..6b698bc17f6 100644 --- a/src/vs/platform/list/browser/listService.ts +++ b/src/vs/platform/list/browser/listService.ts @@ -1145,7 +1145,7 @@ function workbenchTreeDataPreamble(treeRenderIndentGuidesKey); return { @@ -1162,7 +1162,7 @@ function workbenchTreeDataPreamble(treeExpandMode) === 'doubleClick'), contextViewProvider: contextViewService as IContextViewProvider, diff --git a/src/vs/workbench/contrib/files/browser/views/explorerView.ts b/src/vs/workbench/contrib/files/browser/views/explorerView.ts index 76b81a7ed42..55039bcddd0 100644 --- a/src/vs/workbench/contrib/files/browser/views/explorerView.ts +++ b/src/vs/workbench/contrib/files/browser/views/explorerView.ts @@ -450,7 +450,7 @@ export class ExplorerView extends ViewPane implements IExplorerView { } return false; }, - additionalScrollHeight: ExplorerDelegate.ITEM_HEIGHT, + paddingBottom: ExplorerDelegate.ITEM_HEIGHT, overrideStyles: { listBackground: SIDE_BAR_BACKGROUND } diff --git a/src/vs/workbench/contrib/search/browser/searchView.ts b/src/vs/workbench/contrib/search/browser/searchView.ts index 4cdc0341049..b87d1347816 100644 --- a/src/vs/workbench/contrib/search/browser/searchView.ts +++ b/src/vs/workbench/contrib/search/browser/searchView.ts @@ -860,7 +860,7 @@ export class SearchView extends ViewPane { overrideStyles: { listBackground: this.getBackgroundColor() }, - additionalScrollHeight: SearchDelegate.ITEM_HEIGHT + paddingBottom: SearchDelegate.ITEM_HEIGHT })); this._register(this.tree.onContextMenu(e => this.onContextMenu(e))); const updateHasSomeCollapsible = () => this.toggleCollapseStateDelayer.trigger(() => this.hasSomeCollapsibleResultKey.set(this.hasSomeCollapsible())); From d6330cc2a58af3e2658f6acdd88ab1263e4d0d1c Mon Sep 17 00:00:00 2001 From: rebornix Date: Wed, 23 Aug 2023 20:43:36 -0700 Subject: [PATCH 160/221] Update cached map --- .../browser/services/notebookKernelHistoryServiceImpl.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/vs/workbench/contrib/notebook/browser/services/notebookKernelHistoryServiceImpl.ts b/src/vs/workbench/contrib/notebook/browser/services/notebookKernelHistoryServiceImpl.ts index 0a19cda94bf..7901ccc3e16 100644 --- a/src/vs/workbench/contrib/notebook/browser/services/notebookKernelHistoryServiceImpl.ts +++ b/src/vs/workbench/contrib/notebook/browser/services/notebookKernelHistoryServiceImpl.ts @@ -97,6 +97,8 @@ export class NotebookKernelHistoryService extends Disposable implements INoteboo for (const entry of kernels.entries) { linkedMap.set(entry, entry, Touch.AsOld); } + + this._mostRecentKernelsMap[viewType] = linkedMap; } } catch (e) { console.error('Deserialize notebook kernel history failed', e); From 94956b4c3fb38badce912cae3d5a531502669885 Mon Sep 17 00:00:00 2001 From: rebornix Date: Wed, 23 Aug 2023 20:55:52 -0700 Subject: [PATCH 161/221] Fix #189673. Tracking original output id that is reused. --- .../contrib/notebook/browser/notebook.contribution.ts | 4 ++-- .../common/model/notebookCellOutputTextModel.ts | 11 +++++++++++ .../contrib/notebook/common/notebookCommon.ts | 4 ++++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts b/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts index 8bbe932cb1f..2ef3dfb4e8e 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts @@ -455,7 +455,7 @@ class CellInfoContentProvider { let result: { content: string; mode: ILanguageSelection } | undefined = undefined; const mode = this._languageService.createById('json'); - const op = cell.outputs.find(op => op.outputId === data.outputId); + const op = cell.outputs.find(op => op.outputId === data.outputId || op.alternativeOutputId === data.outputId); const streamOutputData = this.parseStreamOutput(op); if (streamOutputData) { result = streamOutputData; @@ -491,7 +491,7 @@ class CellInfoContentProvider { } const ref = await this._notebookModelResolverService.resolve(data.notebook); - const cell = ref.object.notebook.cells.find(cell => !!cell.outputs.find(op => op.outputId === data.outputId)); + const cell = ref.object.notebook.cells.find(cell => !!cell.outputs.find(op => op.outputId === data.outputId || op.alternativeOutputId === data.outputId)); if (!cell) { ref.dispose(); diff --git a/src/vs/workbench/contrib/notebook/common/model/notebookCellOutputTextModel.ts b/src/vs/workbench/contrib/notebook/common/model/notebookCellOutputTextModel.ts index 85ed20571d1..2e2ad62c97e 100644 --- a/src/vs/workbench/contrib/notebook/common/model/notebookCellOutputTextModel.ts +++ b/src/vs/workbench/contrib/notebook/common/model/notebookCellOutputTextModel.ts @@ -25,6 +25,15 @@ export class NotebookCellOutputTextModel extends Disposable implements ICellOutp return this._rawOutput.outputId; } + /** + * Alternative output id that's reused when the output is updated. + */ + private _alternativeOutputId: string; + + get alternativeOutputId(): string { + return this._alternativeOutputId; + } + private _versionId = 0; get versionId() { @@ -35,6 +44,8 @@ export class NotebookCellOutputTextModel extends Disposable implements ICellOutp private _rawOutput: IOutputDto ) { super(); + + this._alternativeOutputId = this._rawOutput.outputId; } replaceData(rawData: IOutputDto) { diff --git a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts index e01a5c37361..8d06fb4cec3 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts @@ -214,6 +214,10 @@ export interface ICellOutput { outputs: IOutputItemDto[]; metadata?: Record; outputId: string; + /** + * Alternative output id that's reused when the output is updated. + */ + alternativeOutputId: string; onDidChangeData: Event; replaceData(items: IOutputDto): void; appendData(items: IOutputItemDto[]): void; From c4b5dff6088ecaffbb8d3f0bdcf26d937bd4c117 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Thu, 24 Aug 2023 09:35:08 +0200 Subject: [PATCH 162/221] fix #189798 (#191090) --- .../preferences/browser/settingsTreeModels.ts | 2 +- .../browser/configurationService.ts | 2 +- .../test/browser/configurationService.test.ts | 16 ++++++++++++++++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/preferences/browser/settingsTreeModels.ts b/src/vs/workbench/contrib/preferences/browser/settingsTreeModels.ts index bcd2604c8d7..180f990b5a5 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsTreeModels.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsTreeModels.ts @@ -273,7 +273,7 @@ export class SettingsTreeSettingElement extends SettingsTreeElement { } private getTargetToInspect(setting: ISetting): SettingsTarget { - if (!this.userDataProfileService.currentProfile.isDefault) { + if (!this.userDataProfileService.currentProfile.isDefault && !this.userDataProfileService.currentProfile.useDefaultFlags?.settings) { if (setting.scope === ConfigurationScope.APPLICATION) { return ConfigurationTarget.APPLICATION; } diff --git a/src/vs/workbench/services/configuration/browser/configurationService.ts b/src/vs/workbench/services/configuration/browser/configurationService.ts index bc40358f62f..d2c05378c9c 100644 --- a/src/vs/workbench/services/configuration/browser/configurationService.ts +++ b/src/vs/workbench/services/configuration/browser/configurationService.ts @@ -47,7 +47,7 @@ import { IBrowserWorkbenchEnvironmentService } from 'vs/workbench/services/envir import { workbenchConfigurationNodeBase } from 'vs/workbench/common/configuration'; function getLocalUserConfigurationScopes(userDataProfile: IUserDataProfile, hasRemote: boolean): ConfigurationScope[] | undefined { - return userDataProfile.isDefault + return (userDataProfile.isDefault || userDataProfile.useDefaultFlags?.settings) ? hasRemote ? LOCAL_MACHINE_SCOPES : undefined : hasRemote ? LOCAL_MACHINE_PROFILE_SCOPES : PROFILE_SCOPES; } diff --git a/src/vs/workbench/services/configuration/test/browser/configurationService.test.ts b/src/vs/workbench/services/configuration/test/browser/configurationService.test.ts index e0613cac0c7..72084f75018 100644 --- a/src/vs/workbench/services/configuration/test/browser/configurationService.test.ts +++ b/src/vs/workbench/services/configuration/test/browser/configurationService.test.ts @@ -1774,6 +1774,22 @@ suite('WorkspaceConfigurationService - Profiles', () => { assert.strictEqual(testObject.getValue('configurationService.profiles.testSetting'), 'profileValue2'); })); + test('switch to non default profile using settings from default profile', () => runWithFakedTimers({ useFakeTimers: true }, async () => { + await fileService.writeFile(instantiationService.get(IUserDataProfilesService).defaultProfile.settingsResource, VSBuffer.fromString('{ "configurationService.profiles.applicationSetting": "applicationValue", "configurationService.profiles.testSetting": "userValue" }')); + await fileService.writeFile(userDataProfileService.currentProfile.settingsResource, VSBuffer.fromString('{ "configurationService.profiles.applicationSetting": "profileValue", "configurationService.profiles.testSetting": "profileValue" }')); + await testObject.reloadConfiguration(); + + const profile = toUserDataProfile('custom3', 'custom3', joinPath(environmentService.userRoamingDataHome, 'profiles', 'custom2'), joinPath(environmentService.cacheHome, 'profilesCache'), { useDefaultFlags: { settings: true } }, instantiationService.get(IUserDataProfilesService).defaultProfile); + await fileService.writeFile(profile.settingsResource, VSBuffer.fromString('{ "configurationService.profiles.applicationSetting": "applicationValue2", "configurationService.profiles.testSetting": "profileValue2" }')); + const promise = Event.toPromise(testObject.onDidChangeConfiguration); + await userDataProfileService.updateCurrentProfile(profile); + + const changeEvent = await promise; + assert.deepStrictEqual([...changeEvent.affectedKeys], ['configurationService.profiles.applicationSetting', 'configurationService.profiles.testSetting']); + assert.strictEqual(testObject.getValue('configurationService.profiles.applicationSetting'), 'applicationValue2'); + assert.strictEqual(testObject.getValue('configurationService.profiles.testSetting'), 'profileValue2'); + })); + test('In non-default profile, changing application settings shall include only application scope settings in the change event', () => runWithFakedTimers({ useFakeTimers: true }, async () => { await fileService.writeFile(instantiationService.get(IUserDataProfilesService).defaultProfile.settingsResource, VSBuffer.fromString('{}')); await testObject.reloadConfiguration(); From 42ff46c8806112de0d04ef92c8fbd7ffaf820055 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 24 Aug 2023 10:35:07 +0200 Subject: [PATCH 163/221] Hovering over an editor tab will "drop a white shadow" on the text (fix #189625) (#191165) --- .../workbench/browser/parts/editor/media/tabstitlecontrol.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/vs/workbench/browser/parts/editor/media/tabstitlecontrol.css b/src/vs/workbench/browser/parts/editor/media/tabstitlecontrol.css index 398e3058b2e..17e17c1a758 100644 --- a/src/vs/workbench/browser/parts/editor/media/tabstitlecontrol.css +++ b/src/vs/workbench/browser/parts/editor/media/tabstitlecontrol.css @@ -297,6 +297,10 @@ padding-right: 5px; /* with tab sizing shrink/fixed and badges, we want a right-padding because the close button is hidden */ } +.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink:not(.tab-actions-left):not(.tab-actions-off) .tab-label { + padding-right: 5px; /* ensure that the gradient does not show when tab actions show https://github.com/microsoft/vscode/issues/189625*/ +} + .monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sticky-compact:not(.has-icon) .monaco-icon-label { text-align: center; /* ensure that sticky-compact tabs without icon have label centered */ } From 7ef754c2f623aa662526e611c67e8e1a97e6753a Mon Sep 17 00:00:00 2001 From: Alpha Romer Coma <400829150120@r3-1.deped.gov.ph> Date: Thu, 24 Aug 2023 08:37:25 +0000 Subject: [PATCH 164/221] Fix supported markdown-lint violations in markdown files (#190750) docs: fix supported markdownlint violations --- .devcontainer/README.md | 5 +- .devcontainer/prebuilt/README.md | 45 +++++++++-------- CONTRIBUTING.md | 2 +- README.md | 8 ++-- SECURITY.md | 14 +++--- build/monaco/README-npm.md | 1 + extensions/git-base/README.md | 9 ++-- extensions/git/README.md | 8 ++-- extensions/javascript/syntaxes/Readme.md | 2 + extensions/json-language-features/README.md | 2 +- .../json-language-features/server/README.md | 29 +++++++---- .../markdown-language-features/README.md | 2 +- .../server/README.md | 46 ++++++++---------- extensions/media-preview/README.md | 1 - extensions/npm/README.md | 4 +- extensions/php-language-features/README.md | 2 +- extensions/simple-browser/README.md | 3 +- .../typescript-basics/syntaxes/Readme.md | 1 + .../web/README.md | 48 ++++++++++--------- .../test/colorize-fixtures/test.md | 2 +- src/vscode-dts/README.md | 9 ++-- test/README.md | 1 + test/integration/browser/README.md | 2 +- test/monaco/README.md | 8 ++-- test/smoke/Audit.md | 12 +++-- test/smoke/README.md | 4 +- test/unit/README.md | 4 +- 27 files changed, 145 insertions(+), 129 deletions(-) diff --git a/.devcontainer/README.md b/.devcontainer/README.md index 6522e98aac9..a5bde90d527 100644 --- a/.devcontainer/README.md +++ b/.devcontainer/README.md @@ -19,13 +19,14 @@ This dev container includes configuration for a development container for workin > **Note:** The Dev Containers extension requires the Visual Studio Code distribution of Code - OSS. See the [FAQ](https://aka.ms/vscode-remote/faq/license) for details. 4. Due to the size of the repository we strongly recommend cloning it on a Linux filesystem for better bind mount performance. On macOS we recommend using a Docker volume (press F1 and select **Dev Containers: Clone Repository in Container Volume...**) and on Windows we recommend using a WSL folder: + - Make sure you are running a recent WSL version to get X11 and Wayland support. - Use the WSL extension for VS Code to open the cloned folder in WSL. - Press F1 and select **Dev Containers: Reopen in Container**. Next: **[Try it out!](#try-it)** -## Try it! +## Try it To start working with Code - OSS, follow these steps: @@ -50,6 +51,6 @@ Next, let's try debugging. Enjoy! -# Notes +## Notes The container comes with VS Code Insiders installed. To run it from an Integrated Terminal use `VSCODE_IPC_HOOK_CLI= /usr/bin/code-insiders .`. diff --git a/.devcontainer/prebuilt/README.md b/.devcontainer/prebuilt/README.md index 82e731230c0..2ca4619ce13 100644 --- a/.devcontainer/prebuilt/README.md +++ b/.devcontainer/prebuilt/README.md @@ -14,21 +14,21 @@ If you already have VS Code and Docker installed, you can click the badge above 2. **Important**: Docker needs at least **4 Cores and 8 GB of RAM** to run a full build with **9 GB of RAM** being recommended. If you are on macOS, or are using the old Hyper-V engine for Windows, update these values for Docker Desktop by right-clicking on the Docker status bar item and going to **Preferences/Settings > Resources > Advanced**. - > **Note:** The [Resource Monitor](https://marketplace.visualstudio.com/items?itemName=mutantdino.resourcemonitor) extension is included in the container so you can keep an eye on CPU/Memory in the status bar. + > **Note:** The [Resource Monitor](https://marketplace.visualstudio.com/items?itemName=mutantdino.resourcemonitor) extension is included in the container so you can keep an eye on CPU/Memory in the status bar. 3. Install [Visual Studio Code Stable](https://code.visualstudio.com/) or [Insiders](https://code.visualstudio.com/insiders/) and the [Dev Containers](https://aka.ms/vscode-remote/download/containers) extension. - ![Image of Dev Containers extension](https://microsoft.github.io/vscode-remote-release/images/dev-containers-extn.png) + ![Image of Dev Containers extension](https://microsoft.github.io/vscode-remote-release/images/dev-containers-extn.png) - > **Note:** The Dev Containers extension requires the Visual Studio Code distribution of Code - OSS. See the [FAQ](https://aka.ms/vscode-remote/faq/license) for details. + > **Note:** The Dev Containers extension requires the Visual Studio Code distribution of Code - OSS. See the [FAQ](https://aka.ms/vscode-remote/faq/license) for details. 4. Press Ctrl/Cmd + Shift + P or F1 and select **Dev Containers: Clone Repository in Container Volume...**. - > **Tip:** While you can use your local source tree instead, operations like `yarn install` can be slow on macOS or when using the Hyper-V engine on Windows. We recommend the "clone repository in container" approach instead since it uses "named volume" rather than the local filesystem. + > **Tip:** While you can use your local source tree instead, operations like `yarn install` can be slow on macOS or when using the Hyper-V engine on Windows. We recommend the "clone repository in container" approach instead since it uses "named volume" rather than the local filesystem. 5. Type `https://github.com/microsoft/vscode` (or a branch or PR URL) in the input box and press Enter. -6. After the container is running, open a web browser and go to [http://localhost:6080](http://localhost:6080), or use a [VNC Viewer](https://www.realvnc.com/en/connect/download/viewer/) to connect to `localhost:5901` and enter `vscode` as the password. +6. After the container is running, open a web browser and go to [http://localhost:6080](http://localhost:6080), or use a [VNC Viewer][def] to connect to `localhost:5901` and enter `vscode` as the password. Anything you start in VS Code, or the integrated terminal, will appear here. @@ -54,41 +54,42 @@ Next: **[Try it out!](#try-it)** ### Using VS Code with GitHub Codespaces -You may see improved VNC responsiveness when accessing a codespace from VS Code client since you can use a [VNC Viewer](https://www.realvnc.com/en/connect/download/viewer/). Here's how to do it. +You may see improved VNC responsiveness when accessing a codespace from VS Code client since you can use a [VNC Viewer][def]. Here's how to do it. -1. Install [Visual Studio Code Stable](https://code.visualstudio.com/) or [Insiders](https://code.visualstudio.com/insiders/) and the the [GitHub Codespaces extension](https://marketplace.visualstudio.com/items?itemName=GitHub.codespaces). +1. Install [Visual Studio Code Stable](https://code.visualstudio.com/) or [Insiders](https://code.visualstudio.com/insiders/) and the the [GitHub Codespaces extension](https://marketplace.visualstudio.com/items?itemName=GitHub.codespaces). - > **Note:** The GitHub Codespaces extension requires the Visual Studio Code distribution of Code - OSS. + > **Note:** The GitHub Codespaces extension requires the Visual Studio Code distribution of Code - OSS. 2. After the VS Code is up and running, press Ctrl/Cmd + Shift + P or F1, choose **Codespaces: Create New Codespace**, and use the following settings: - - `microsoft/vscode` for the repository. - - Select any branch (e.g. **main**) - you can select a different one later. - - Choose **Standard** (4-core, 8GB) as the size. -4. After you have connected to the codespace, you can use a [VNC Viewer](https://www.realvnc.com/en/connect/download/viewer/) to connect to `localhost:5901` and enter `vscode` as the password. +- `microsoft/vscode` for the repository. +- Select any branch (e.g. **main**) - you can select a different one later. +- Choose **Standard** (4-core, 8GB) as the size. + +3. After you have connected to the codespace, you can use a [VNC Viewer][def] to connect to `localhost:5901` and enter `vscode` as the password. > **Tip:** You may also need change your VNC client's **Picture Quality** setting to **High** to get a full color desktop. -5. Anything you start in VS Code, or the integrated terminal, will appear here. +4. Anything you start in VS Code, or the integrated terminal, will appear here. Next: **[Try it out!](#try-it)** -## Try it! +## Try it This container uses the [Fluxbox](http://fluxbox.org/) window manager to keep things lean. **Right-click on the desktop** to see menu options. It works with GNOME and GTK applications, so other tools can be installed if needed. -> **Note:** You can also set the resolution from the command line by typing `set-resolution`. + > **Note:** You can also set the resolution from the command line by typing `set-resolution`. To start working with Code - OSS, follow these steps: 1. In your local VS Code client, open a terminal (Ctrl/Cmd + Shift + \`) and type the following commands: - ```bash - yarn install - bash scripts/code.sh - ``` + ```bash + yarn install + bash scripts/code.sh + ``` -2. After the build is complete, open a web browser or a [VNC Viewer](https://www.realvnc.com/en/connect/download/viewer/) to connect to the desktop environment as described in the quick start and enter `vscode` as the password. +2. After the build is complete, open a web browser or a [VNC Viewer][def] to connect to the desktop environment as described in the quick start and enter `vscode` as the password. 3. You should now see Code - OSS! @@ -98,8 +99,10 @@ Next, let's try debugging. 2. Go to your local VS Code client, and use the **Run / Debug** view to launch the **VS Code** configuration. (Typically the default, so you can likely just press F5). - > **Note:** If launching times out, you can increase the value of `timeout` in the "VS Code", "Attach Main Process", "Attach Extension Host", and "Attach to Shared Process" configurations in [launch.json](../../.vscode/launch.json). However, running `scripts/code.sh` first will set up Electron which will usually solve timeout issues. + > **Note:** If launching times out, you can increase the value of `timeout` in the "VS Code", "Attach Main Process", "Attach Extension Host", and "Attach to Shared Process" configurations in [launch.json](../../.vscode/launch.json). However, running `scripts/code.sh` first will set up Electron which will usually solve timeout issues. 3. After a bit, Code - OSS will appear with the debugger attached! Enjoy! + +[def]: https://www.realvnc.com/en/connect/download/viewer/ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b96e077aa67..f17fa843645 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -104,6 +104,6 @@ If you believe the bot got something wrong, please open a new issue and let us k If you are interested in writing code to fix issues, please see [How to Contribute](https://github.com/microsoft/vscode/wiki/How-to-Contribute) in the wiki. -# Thank You! +## Thank You Your contributions to open source, large or small, make great projects like this possible. Thank you for taking the time to contribute. diff --git a/README.md b/README.md index 0c7c6236c42..61df8fc6bb4 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ # Visual Studio Code - Open Source ("Code - OSS") + [![Feature Requests](https://img.shields.io/github/issues/microsoft/vscode/feature-request.svg)](https://github.com/microsoft/vscode/issues?q=is%3Aopen+is%3Aissue+label%3Afeature-request+sort%3Areactions-%2B1-desc) [![Bugs](https://img.shields.io/github/issues/microsoft/vscode/bug.svg)](https://github.com/microsoft/vscode/issues?utf8=✓&q=is%3Aissue+is%3Aopen+label%3Abug) [![Gitter](https://img.shields.io/badge/chat-on%20gitter-yellow.svg)](https://gitter.im/Microsoft/vscode) @@ -60,9 +61,10 @@ VS Code includes a set of built-in extensions located in the [extensions](extens This repository includes a Visual Studio Code Dev Containers / GitHub Codespaces development container. -- For [Dev Containers](https://aka.ms/vscode-remote/download/containers), use the **Dev Containers: Clone Repository in Container Volume...** command which creates a Docker volume for better disk I/O on macOS and Windows. - - If you already have VS Code and Docker installed, you can also click [here](https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url=https://github.com/microsoft/vscode) to get started. This will cause VS Code to automatically install the Dev Containers extension if needed, clone the source code into a container volume, and spin up a dev container for use. -- For Codespaces, install the [GitHub Codespaces](https://marketplace.visualstudio.com/items?itemName=GitHub.codespaces) extension in VS Code, and use the **Codespaces: Create New Codespace** command. +* For [Dev Containers](https://aka.ms/vscode-remote/download/containers), use the **Dev Containers: Clone Repository in Container Volume...** command which creates a Docker volume for better disk I/O on macOS and Windows. + * If you already have VS Code and Docker installed, you can also click [here](https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url=https://github.com/microsoft/vscode) to get started. This will cause VS Code to automatically install the Dev Containers extension if needed, clone the source code into a container volume, and spin up a dev container for use. + +* For Codespaces, install the [GitHub Codespaces](https://marketplace.visualstudio.com/items?itemName=GitHub.codespaces) extension in VS Code, and use the **Codespaces: Create New Codespace** command. Docker / the Codespace should have at least **4 Cores and 6 GB of RAM (8 GB recommended)** to run full build. See the [development container README](.devcontainer/README.md) for more information. diff --git a/SECURITY.md b/SECURITY.md index a050f362c15..4fa5946a867 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -18,13 +18,13 @@ You should receive a response within 24 hours. If for some reason you do not, pl Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: - * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) - * Full paths of source file(s) related to the manifestation of the issue - * The location of the affected source code (tag/branch/commit or direct URL) - * Any special configuration required to reproduce the issue - * Step-by-step instructions to reproduce the issue - * Proof-of-concept or exploit code (if possible) - * Impact of the issue, including how an attacker might exploit the issue +* Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) +* Full paths of source file(s) related to the manifestation of the issue +* The location of the affected source code (tag/branch/commit or direct URL) +* Any special configuration required to reproduce the issue +* Step-by-step instructions to reproduce the issue +* Proof-of-concept or exploit code (if possible) +* Impact of the issue, including how an attacker might exploit the issue This information will help us triage your report more quickly. diff --git a/build/monaco/README-npm.md b/build/monaco/README-npm.md index ca5592e0fe1..ec8eb5a4037 100644 --- a/build/monaco/README-npm.md +++ b/build/monaco/README-npm.md @@ -10,4 +10,5 @@ The Monaco Editor is the code editor that powers [VS Code](https://github.com/mi This npm module contains the core editor functionality, as it comes from the [vscode repository](https://github.com/microsoft/vscode). ## License + [MIT](https://github.com/microsoft/vscode/blob/main/LICENSE.txt) diff --git a/extensions/git-base/README.md b/extensions/git-base/README.md index ff5bcc321c7..d6f0b7c128b 100644 --- a/extensions/git-base/README.md +++ b/extensions/git-base/README.md @@ -14,7 +14,8 @@ The Git extension exposes an API, reachable by any other extension. 2. Include `git-base.d.ts` in your extension's compilation. 3. Get a hold of the API with the following snippet: - ```ts - const gitBaseExtension = vscode.extensions.getExtension('vscode.git-base').exports; - const git = gitBaseExtension.getAPI(1); - ``` + ```ts + const gitBaseExtension = vscode.extensions.getExtension('vscode.git-base').exports; + const git = gitBaseExtension.getAPI(1); + + ``` diff --git a/extensions/git/README.md b/extensions/git/README.md index a20f3207534..2a6678de933 100644 --- a/extensions/git/README.md +++ b/extensions/git/README.md @@ -14,7 +14,7 @@ The Git extension exposes an API, reachable by any other extension. 2. Include `git.d.ts` in your extension's compilation. 3. Get a hold of the API with the following snippet: - ```ts - const gitExtension = vscode.extensions.getExtension('vscode.git').exports; - const git = gitExtension.getAPI(1); - ``` \ No newline at end of file + ```ts + const gitExtension = vscode.extensions.getExtension('vscode.git').exports; + const git = gitExtension.getAPI(1); + ``` diff --git a/extensions/javascript/syntaxes/Readme.md b/extensions/javascript/syntaxes/Readme.md index bc29199fd73..b7db3a6a4c9 100644 --- a/extensions/javascript/syntaxes/Readme.md +++ b/extensions/javascript/syntaxes/Readme.md @@ -1,10 +1,12 @@ The file `JavaScript.tmLanguage.json` is derived from [TypeScriptReact.tmLanguage](https://github.com/microsoft/TypeScript-TmLanguage/blob/master/TypeScriptReact.tmLanguage). To update to the latest version: + - `cd extensions/typescript` and run `npm run update-grammars` - don't forget to run the integration tests at `./scripts/test-integration.sh` The script does the following changes: + - fileTypes .tsx -> .js & .jsx - scopeName scope.tsx -> scope.js - update all rule names .tsx -> .js diff --git a/extensions/json-language-features/README.md b/extensions/json-language-features/README.md index 2ff5e6e57d3..3de3d11081a 100644 --- a/extensions/json-language-features/README.md +++ b/extensions/json-language-features/README.md @@ -4,4 +4,4 @@ ## Features -See [JSON in Visual Studio Code](https://code.visualstudio.com/docs/languages/json) to learn about the features of this extension. \ No newline at end of file +See [JSON in Visual Studio Code](https://code.visualstudio.com/docs/languages/json) to learn about the features of this extension. diff --git a/extensions/json-language-features/server/README.md b/extensions/json-language-features/server/README.md index e9875ba5977..10956439e32 100644 --- a/extensions/json-language-features/server/README.md +++ b/extensions/json-language-features/server/README.md @@ -11,6 +11,7 @@ The JSON Language server provides language-specific smarts for editing, validati ### Server capabilities The JSON language server supports requests on documents of language id `json` and `jsonc`. + - `json` documents are parsed and validated following the [JSON specification](https://tools.ietf.org/html/rfc7159). - `jsonc` documents additionally accept single line (`//`) and multi-line comments (`/* ... */`). JSONC is a VSCode specific file format, intended for VSCode configuration files, without any aspirations to define a new common file format. @@ -25,12 +26,12 @@ The server implements the following capabilities of the language server protocol - Semantic Selection for semantic selection for one or multiple cursor positions. - [Goto Definition](https://microsoft.github.io/language-server-protocol/specification#textDocument_definition) for $ref references in JSON schemas - [Diagnostics (Validation)](https://microsoft.github.io/language-server-protocol/specification#textDocument_publishDiagnostics) are pushed for all open documents - - syntax errors - - structural validation based on the document's [JSON schema](http://json-schema.org/). + - syntax errors + - structural validation based on the document's [JSON schema](http://json-schema.org/). In order to load JSON schemas, the JSON server uses NodeJS `http` and `fs` modules. For all other features, the JSON server only relies on the documents and settings provided by the client through the LSP. -### Client requirements: +### Client requirements The JSON language server expects the client to only send requests and notifications for documents of language id `json` and `jsonc`. @@ -56,8 +57,8 @@ Clients may send a `workspace/didChangeConfiguration` notification to notify the The server supports the following settings: - http - - `proxy`: The URL of the proxy server to use when fetching schema. When undefined or empty, no proxy is used. - - `proxyStrictSSL`: Whether the proxy server certificate should be verified against the list of supplied CAs. + - `proxy`: The URL of the proxy server to use when fetching schema. When undefined or empty, no proxy is used. + - `proxyStrictSSL`: Whether the proxy server certificate should be verified against the list of supplied CAs. - json - `format` @@ -72,6 +73,7 @@ The server supports the following settings: - `resultLimit`: The max number of color decorators and outline symbols to be computed (for performance reasons) - `jsonFoldingLimit`: The max number of folding ranges to be computed for json documents (for performance reasons) - `jsoncFoldingLimit`: The max number of folding ranges to be computed for jsonc documents (for performance reasons) + ```json { "http": { @@ -103,6 +105,7 @@ The server supports the following settings: [JSON schemas](http://json-schema.org/) are essential for code assist, hovers, color decorators to work and are required for structural validation. To find the schema for a given JSON document, the server uses the following mechanisms: + - JSON documents can define the schema URL using a `$schema` property - The settings define a schema association based on the documents URL. Settings can either associate a schema URL to a file or path pattern, and they can directly provide a schema. - Additionally, schema associations can also be provided by a custom 'schemaAssociations' configuration call. @@ -115,9 +118,9 @@ The `initializationOptions.handledSchemaProtocols` initialization option defines ```ts let clientOptions: LanguageClientOptions = { - initializationOptions: { - handledSchemaProtocols: ['file'] // language server should only try to load file URLs - } + initializationOptions: { + handledSchemaProtocols: ['file'] // language server should only try to load file URLs + } ... } ``` @@ -132,6 +135,7 @@ If `handledSchemaProtocols` is not set, the JSON language server will load the f Requests for schemas with URLs not handled by the server are forwarded to the client through an LSP request. This request is a JSON language server-specific, non-standardized, extension to the LSP. Request: + - method: 'vscode/content' - params: `string` - The schema URL to request. - response: `string` - The content of the schema with the given URL @@ -146,6 +150,7 @@ The server will, as a response, clear the schema content from the cache and relo In addition to the settings, schemas associations can also be provided through a notification from the client to the server. This notification is a JSON language server-specific, non-standardized, extension to the LSP. Notification: + - method: 'json/schemaAssociations' - params: `ISchemaAssociations` or `ISchemaAssociation[]` defined as follows @@ -183,11 +188,14 @@ interface ISchemaAssociation { } ``` + `ISchemaAssociations` - - keys: a file names or file path (separated by `/`). `*` can be used as a wildcard. - - values: An array of schema URLs + +- keys: a file names or file path (separated by `/`). `*` can be used as a wildcard. +- values: An array of schema URLs Notification: + - method: 'json/schemaContent' - params: `string` the URL of the schema that has changed. @@ -226,6 +234,7 @@ The source code of the JSON language server can be found in the [VSCode reposito File issues and pull requests in the [VSCode GitHub Issues](https://github.com/microsoft/vscode/issues). See the document [How to Contribute](https://github.com/microsoft/vscode/wiki/How-to-Contribute) on how to build and run from source. Most of the functionality of the server is located in libraries: + - [jsonc-parser](https://github.com/microsoft/node-jsonc-parser) contains the JSON parser and scanner. - [vscode-json-languageservice](https://github.com/microsoft/vscode-json-languageservice) contains the implementation of all features as a re-usable library. - [vscode-languageserver-node](https://github.com/microsoft/vscode-languageserver-node) contains the implementation of language server for NodeJS. diff --git a/extensions/markdown-language-features/README.md b/extensions/markdown-language-features/README.md index e80e9e886bb..2052521da84 100644 --- a/extensions/markdown-language-features/README.md +++ b/extensions/markdown-language-features/README.md @@ -4,4 +4,4 @@ ## Features -See [Markdown in Visual Studio Code](https://code.visualstudio.com/docs/languages/markdown) to learn about the features of this extension. \ No newline at end of file +See [Markdown in Visual Studio Code](https://code.visualstudio.com/docs/languages/markdown) to learn about the features of this extension. diff --git a/extensions/markdown-language-features/server/README.md b/extensions/markdown-language-features/server/README.md index 1fd38302195..4114d2698bf 100644 --- a/extensions/markdown-language-features/server/README.md +++ b/extensions/markdown-language-features/server/README.md @@ -6,7 +6,6 @@ The Markdown language server powers VS Code's built-in markdown support, providi This server uses the [Markdown Language Service](https://github.com/microsoft/vscode-markdown-languageservice) to implement almost all of the language features. You can use that library if you need a library for working with Markdown instead of a full language server. - ## Server capabilities - [Completions](https://microsoft.github.io/language-server-protocol/specification#textDocument_completion) for Markdown links. @@ -31,14 +30,13 @@ This server uses the [Markdown Language Service](https://github.com/microsoft/vs - [Code Actions](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_codeAction) - - Organize link definitions source action. - - Extract link to definition refactoring. + - Organize link definitions source action. + - Extract link to definition refactoring. - Updating links when a file is moved / renamed. Uses a custom `markdown/getEditForFileRenames` message. - [Pull diagnostics (validation)](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_pullDiagnostics) for links. - ## Client requirements ### Initialization options @@ -53,27 +51,27 @@ Clients may send a `workspace/didChangeConfiguration` notification to notify the The server supports the following settings: - `markdown` - - `suggest` - - `paths` - - `enabled` — Enable/disable path suggestions. + - `suggest` + - `paths` + - `enabled` — Enable/disable path suggestions. - - `occurrencesHighlight` - - `enabled` — Enable/disable highlighting of link occurrences. + - `occurrencesHighlight` + - `enabled` — Enable/disable highlighting of link occurrences. - - `validate` - - `enabled` — Enable/disable all validation. - - `referenceLinks` - - `enabled` — Enable/disable validation of reference links: `[text][ref]` - - `fragmentLinks` - - `enabled` — Enable/disable validation of links to fragments in the current files: `[text](#head)` - - `fileLinks` - - `enabled` — Enable/disable validation of links to file in the workspace. - - `markdownFragmentLinks` — Enable/disable validation of links to headers in other Markdown files. Use `inherit` to inherit the `fragmentLinks` setting. - - `ignoredLinks` — Array of glob patterns for files that should not be validated. - - `unusedLinkDefinitions` - - `enabled` — Enable/disable validation of unused link definitions. - - `duplicateLinkDefinitions` - - `enabled` — Enable/disable validation of duplicated link definitions. + - `validate` + - `enabled` — Enable/disable all validation. + - `referenceLinks` + - `enabled` — Enable/disable validation of reference links: `[text][ref]` + - `fragmentLinks` + - `enabled` — Enable/disable validation of links to fragments in the current files: `[text](#head)` + - `fileLinks` + - `enabled` — Enable/disable validation of links to file in the workspace. + - `markdownFragmentLinks` — Enable/disable validation of links to headers in other Markdown files. Use `inherit` to inherit the `fragmentLinks` setting. + - `ignoredLinks` — Array of glob patterns for files that should not be validated. + - `unusedLinkDefinitions` + - `enabled` — Enable/disable validation of unused link definitions. + - `duplicateLinkDefinitions` + - `enabled` — Enable/disable validation of duplicated link definitions. ### Custom requests @@ -109,7 +107,6 @@ Delete a previously created file watcher. Get a list of all markdown files in the workspace. - ## Contribute The source code of the Markdown language server can be found in the [VSCode repository](https://github.com/microsoft/vscode) at [extensions/markdown-language-features/server](https://github.com/microsoft/vscode/tree/master/extensions/markdown-language-features/server). @@ -132,4 +129,3 @@ This project has adopted the [Microsoft Open Source Code of Conduct](https://ope Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the [MIT](https://github.com/microsoft/vscode/blob/master/LICENSE.txt) License. - diff --git a/extensions/media-preview/README.md b/extensions/media-preview/README.md index 48428a684bf..8163e017143 100644 --- a/extensions/media-preview/README.md +++ b/extensions/media-preview/README.md @@ -16,7 +16,6 @@ This extension provides basic preview for images, audio and video files. - `.webp` - `.avif` - ### Supported audio formats - `.mp3` diff --git a/extensions/npm/README.md b/extensions/npm/README.md index 82730c7e82a..296bf03f73e 100644 --- a/extensions/npm/README.md +++ b/extensions/npm/README.md @@ -28,7 +28,7 @@ The extension supports running a script as a task from a folder in the Explorer. ### Others -The extension fetches data from https://registry.npmjs.org and https://registry.bower.io to provide auto-completion and information on hover features on npm dependencies. +The extension fetches data from and to provide auto-completion and information on hover features on npm dependencies. ## Settings @@ -40,5 +40,3 @@ The extension fetches data from https://registry.npmjs.org and https://registry. - `npm.scriptExplorerAction` - The default click action: `open` or `run`, the default is `open`. - `npm.enableRunFromFolder` - Enable running npm scripts from the context menu of folders in Explorer, the default is `false`. - `npm.scriptCodeLens.enable` - Enable/disable the code lenses to run a script, the default is `false`. - - diff --git a/extensions/php-language-features/README.md b/extensions/php-language-features/README.md index c00be6a964e..e0d28f5254f 100644 --- a/extensions/php-language-features/README.md +++ b/extensions/php-language-features/README.md @@ -4,4 +4,4 @@ ## Features -See [PHP in Visual Studio Code](https://code.visualstudio.com/docs/languages/php) to learn about the features of this extension. \ No newline at end of file +See [PHP in Visual Studio Code](https://code.visualstudio.com/docs/languages/php) to learn about the features of this extension. diff --git a/extensions/simple-browser/README.md b/extensions/simple-browser/README.md index b4ecf7a4ad6..5121dc86e89 100644 --- a/extensions/simple-browser/README.md +++ b/extensions/simple-browser/README.md @@ -2,5 +2,4 @@ **Notice:** This extension is bundled with Visual Studio Code. It can be disabled but not uninstalled. -Provides a very basic browser preview using an iframe embedded in a [webview](). This extension is primarily meant to be used by other extensions for showing simple web content. - +Provides a very basic browser preview using an iframe embedded in a [webviewW](). This extension is primarily meant to be used by other extensions for showing simple web content. diff --git a/extensions/typescript-basics/syntaxes/Readme.md b/extensions/typescript-basics/syntaxes/Readme.md index 2f9c2b95ee2..fa05c28d970 100644 --- a/extensions/typescript-basics/syntaxes/Readme.md +++ b/extensions/typescript-basics/syntaxes/Readme.md @@ -1,6 +1,7 @@ The file `TypeScript.tmLanguage.json` and `TypeScriptReact.tmLanguage.json` are derived from [TypeScript.tmLanguage](https://github.com/microsoft/TypeScript-TmLanguage/blob/master/TypeScript.tmLanguage) and [TypeScriptReact.tmLanguage](https://github.com/microsoft/TypeScript-TmLanguage/blob/master/TypeScriptReact.tmLanguage). To update to the latest version: + - `cd extensions/typescript` and run `npm run update-grammars` - don't forget to run the integration tests at `./scripts/test-integration.sh` diff --git a/extensions/typescript-language-features/web/README.md b/extensions/typescript-language-features/web/README.md index 9cae35b8cf3..a9c19b5d72a 100644 --- a/extensions/typescript-language-features/web/README.md +++ b/extensions/typescript-language-features/web/README.md @@ -1,4 +1,5 @@ # vscode-wasm-typescript + Language server host for typescript using vscode's sync-api in the browser ## TODOs @@ -22,33 +23,33 @@ Language server host for typescript using vscode's sync-api in the browser - LATER: Turns out you can skip the existing server by depending on tsserverlibrary instead of tsserver. - [x] figure out a webpack-native way to generate tsserver.web.js if possible - [x] path rewriting is pretty loosey-goosey; likely to be incorrect some of the time - - invert the logic from TypeScriptServiceClient.normalizedPath for requests - - invert the function from webServer.ts for responses (maybe) - - something with getWorkspaceRootForResource (or anything else that checks `resouce.scheme`) + - invert the logic from TypeScriptServiceClient.normalizedPath for requests + - invert the function from webServer.ts for responses (maybe) + - something with getWorkspaceRootForResource (or anything else that checks `resouce.scheme`) - [x] put files one level down from virtual root - [x] fill in missing environment files like lib.dom.d.ts - - toResource's isWeb branch *probably* knows where to find this, just need to put it in the virtual FS - - I guess during setup in serverProcess.browser.ts. - - Not sure whether it needs to have the data or just a fs entry. - - Wait, I don't know how files get added to the FS normally. + - toResource's isWeb branch *probably* knows where to find this, just need to put it in the virtual FS + - I guess during setup in serverProcess.browser.ts. + - Not sure whether it needs to have the data or just a fs entry. + - Wait, I don't know how files get added to the FS normally. - [x] cancellation should only retain one cancellation checker - - the one that matches the current request id - - but that means tracking (or retrieving from tsserver) the request id (aka seq?) - - and correctly setting/resetting it on the cancellation token too. - - I looked at the tsserver code. I think the web case is close to the single-pipe node case, + - the one that matches the current request id + - but that means tracking (or retrieving from tsserver) the request id (aka seq?) + - and correctly setting/resetting it on the cancellation token too. + - I looked at the tsserver code. I think the web case is close to the single-pipe node case, so I just require that requestId is set in order to call the *current* cancellation checker. - - Any incoming message with a cancellation checker will overwrite the current one. + - Any incoming message with a cancellation checker will overwrite the current one. - [x] Cancellation code in vscode is suspiciously prototypey. - - Specifically, it adds the vscode-wasm cancellation to original cancellation code, but should actually switch to the former for web only. - - looks like `isWeb()` is a way to check for being on the web + - Specifically, it adds the vscode-wasm cancellation to original cancellation code, but should actually switch to the former for web only. + - looks like `isWeb()` is a way to check for being on the web - [x] create multiple watchers - - on-demand instead of watching everything and checking on watch firing + - on-demand instead of watching everything and checking on watch firing - [x] get file watching to work - - it could *already* work, I just don't know how to test it - - look at extensions/markdown-language-features/src/client/fileWatchingManager.ts to see if I can use that - - later: it is OK. its main difference is that you can watch files in not-yet-created directories, and it maintains + - it could *already* work, I just don't know how to test it + - look at extensions/markdown-language-features/src/client/fileWatchingManager.ts to see if I can use that + - later: it is OK. its main difference is that you can watch files in not-yet-created directories, and it maintains a web of directory watches that then check whether the file is eventually created. - - even later: well, it works even though it is similar to my code. + - even later: well, it works even though it is similar to my code. I'm not sure what is different. - [x] copy fileWatchingManager.ts to web/ ; there's no sharing code between extensions - [x] Find out scheme the web actually uses instead of vscode-test-web (or switch over entirely to isWeb) @@ -106,6 +107,7 @@ Language server host for typescript using vscode's sync-api in the browser - so I can just redo whatever that did and it'll be fine ### Done + - [x] need to update 0.2 -> 0.7.* API (once it's working properly) - [x] including reshuffling the webpack hack if needed - [x] need to use the settings recommended by Sheetal @@ -113,7 +115,7 @@ Language server host for typescript using vscode's sync-api in the browser - [x] sync-api-client says fs is rooted at memfs:/sample-folder; the protocol 'memfs:' is confusing our file parsing I think - [x] nothing ever seems to find tsconfig.json - [x] messages aren't actually coming through, just the message from the first request - - fixed by simplifying the listener setup for now + - fixed by simplifying the listener setup for now - [x] once messages work, you can probably log by postMessage({ type: 'log', body: "some logging text" }) - [x] implement realpath, modifiedtime, resolvepath, then turn semantic mode on - [x] file watching implemented with saved map of filename to callback, and forwarding @@ -125,6 +127,7 @@ Language server host for typescript using vscode's sync-api in the browser ## Notes messages received by extension AND host use paths like ^/memfs/ts-nul-authority/sample-folder/file.ts + - problem: pretty sure the extension doesn't know what to do with that: it's not putting down error spans in file.ts - question: why is the extension requesting quickinfo in that URI format? And it works! (probably because the result is a tooltip, not an in-file span) - problem: weird concatenations with memfs:/ in the middle @@ -140,15 +143,14 @@ but readFile is getting called with things like memfs:/sample-folder/memfs:/type watchDirectory with /sample-folder/^ and directoryExists with /sample-folder/^/memfs/ts-nul-authority/sample-folder/workspaces/ watchFile with /sample-folder/memfs:/sample-folder/memfs:/lib.es2020.full.d.ts -### LATER: +### LATER OK, so the paths that tsserver has look like this: ^/scheme/mount/whatever.ts but the paths the filesystem has look like this: scheme:/whatever.ts (not sure about 'mount', that's only when cloning from the fs) so you have to shave off the scheme that the host combined with the path and put on the scheme that the vfs is using. -### LATER 2: +### LATER 2 Some commands ask for getExecutingFilePath or getCurrentDirectory and cons up a path themselves. This works, because URI.from({ scheme, path }) matches what the fs has in it Problem: In *some* messages (all?), vscode then refers to /x.ts and ^/vscode-test-web/mount/x.ts (or ^/memfs/ts-nul-authority/x.ts) - diff --git a/extensions/vscode-colorize-tests/test/colorize-fixtures/test.md b/extensions/vscode-colorize-tests/test/colorize-fixtures/test.md index 28f3590536e..309aa6de793 100644 --- a/extensions/vscode-colorize-tests/test/colorize-fixtures/test.md +++ b/extensions/vscode-colorize-tests/test/colorize-fixtures/test.md @@ -103,4 +103,4 @@ Pop * Multiple definitions and terms are possible * Definitions can include multiple paragraphs too -*[ABBR]: Markdown plus abbreviations (produces an tag) \ No newline at end of file +*[ABBR]: Markdown plus abbreviations (produces an tag) diff --git a/src/vscode-dts/README.md b/src/vscode-dts/README.md index a69e5eb65e1..9b3640d9208 100644 --- a/src/vscode-dts/README.md +++ b/src/vscode-dts/README.md @@ -1,18 +1,17 @@ -## vscode-dts +# vscode-dts This is the place for the stable API and for API proposals. - -### Consume a proposal +## Consume a proposal 1. find a proposal you are interested in 1. add its name to your extensions `package.json#enabledApiProposals` property 1. run `npx vscode-dts dev` to download the `d.ts` files into your project 1. don't forget that extension using proposed API cannot be published -1. learn more here: https://code.visualstudio.com/api/advanced-topics/using-proposed-api +1. learn more here: -### Add a new proposal +## Add a new proposal 1. create a _new_ file in this directory, its name must follow this pattern `vscode.proposed.[a-zA-Z]+.d.ts` 1. creating the proposal-file will automatically update `src/vs/workbench/services/extensions/common/extensionsApiProposals.ts` (make sure to run `yarn watch`) diff --git a/test/README.md b/test/README.md index 80cf9d92912..1e4d114dce5 100644 --- a/test/README.md +++ b/test/README.md @@ -3,6 +3,7 @@ ## Contents This folder contains the various test runners for VSCode. Please refer to the documentation within for how to run them: + * `unit`: our suite of unit tests ([README](unit/README.md)) * `integration`: our suite of API tests ([README](integration/browser/README.md)) * `smoke`: our suite of automated UI tests ([README](smoke/README.md)) diff --git a/test/integration/browser/README.md b/test/integration/browser/README.md index 34107241f8e..8b25994564d 100644 --- a/test/integration/browser/README.md +++ b/test/integration/browser/README.md @@ -21,7 +21,7 @@ All integration tests run in a browser instance as specified by the command line Add the `--debug` flag to see a browser window with the tests running. -**Note**: you can enable verbose logging of playwright library by setting a `DEBUG` environment variable before running the tests (https://playwright.dev/docs/debug#verbose-api-logs) +**Note**: you can enable verbose logging of playwright library by setting a `DEBUG` environment variable before running the tests () ## Debug diff --git a/test/monaco/README.md b/test/monaco/README.md index 68bb7051ce8..e55338934f2 100644 --- a/test/monaco/README.md +++ b/test/monaco/README.md @@ -4,10 +4,10 @@ This directory contains scripts that are used to smoke test the Monaco Editor di ## Setup & Bundle - $test/monaco> yarn - $test/monaco> yarn run bundle + $test/monaco> yarn + $test/monaco> yarn run bundle ## Compile and run tests - $test/monaco> yarn run compile - $test/monaco> yarn test + $test/monaco> yarn run compile + $test/monaco> yarn test diff --git a/test/smoke/Audit.md b/test/smoke/Audit.md index 4ec76567e9c..fd8913b44e2 100644 --- a/test/smoke/Audit.md +++ b/test/smoke/Audit.md @@ -1,13 +1,15 @@ # VS Code Smoke Tests Failures History + This file contains a history of smoke test failures which could be avoided if particular techniques were used in the test (e.g. binding test elements with HTML5 `data-*` attribute). To better understand what can be employed in smoke test to ensure its stability, it is important to understand patterns that led to smoke test breakage. This markdown is a result of work on [this issue](https://github.com/microsoft/vscode/issues/27906). -# Log -1. This following change led to the smoke test failure because DOM element's attribute `a[title]` was changed: - [eac49a3](https://github.com/microsoft/vscode/commit/eac49a321b84cb9828430e9dcd3f34243a3480f7) +## Log - This attribute was used in the smoke test to grab the contents of SCM part in status bar: - [0aec2d6](https://github.com/microsoft/vscode/commit/0aec2d6838b5e65cc74c33b853ffbd9fa191d636) +1. This following change led to the smoke test failure because DOM element's attribute `a[title]` was changed: + [eac49a3](https://github.com/microsoft/vscode/commit/eac49a321b84cb9828430e9dcd3f34243a3480f7) + + This attribute was used in the smoke test to grab the contents of SCM part in status bar: + [0aec2d6](https://github.com/microsoft/vscode/commit/0aec2d6838b5e65cc74c33b853ffbd9fa191d636) 2. To be continued... diff --git a/test/smoke/README.md b/test/smoke/README.md index ffef4c28339..9b5eb6282b4 100644 --- a/test/smoke/README.md +++ b/test/smoke/README.md @@ -2,7 +2,7 @@ Make sure you are on **Node v12.x**. -### Quick Overview +## Quick Overview ```bash # Build extensions in the VS Code repo (if needed) @@ -57,7 +57,7 @@ xattr -d com.apple.quarantine - `-f PATTERN` (alias `-g PATTERN`) filters the tests to be run. You can also use pretty much any mocha argument; - `--headless` will run playwright in headless mode when `--web` is used. -**Note**: you can enable verbose logging of playwright library by setting a `DEBUG` environment variable before running the tests (https://playwright.dev/docs/debug#verbose-api-logs), for example to `pw:browser`. +**Note**: you can enable verbose logging of playwright library by setting a `DEBUG` environment variable before running the tests (), for example to `pw:browser`. ### Develop diff --git a/test/unit/README.md b/test/unit/README.md index 58d569d571f..154f1cf0ad0 100644 --- a/test/unit/README.md +++ b/test/unit/README.md @@ -33,10 +33,10 @@ Unit tests from layers `common` and `browser` are run inside `chromium`, `webkit The following command will create a `coverage` folder in the `.build` folder at the root of the workspace: -**OS X and Linux** +### OS X and Linux ./scripts/test.sh --coverage -**Windows** +### Windows scripts\test --coverage From ca86548968a4ea83a56cbe3b16a36888fbf41213 Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Thu, 24 Aug 2023 10:57:12 +0200 Subject: [PATCH 165/221] changing from a js doc to a doc --- .../src/configuration/configuration.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/typescript-language-features/src/configuration/configuration.ts b/extensions/typescript-language-features/src/configuration/configuration.ts index 23b1ee8b466..d338792c58c 100644 --- a/extensions/typescript-language-features/src/configuration/configuration.ts +++ b/extensions/typescript-language-features/src/configuration/configuration.ts @@ -200,7 +200,7 @@ export abstract class BaseServiceConfigurationProvider implements ServiceConfigu } protected readEnableDiagnosticsTelemetry(configuration: vscode.WorkspaceConfiguration): boolean { - /** This setting does not appear in the settings view, as it is not to be enabled by users outside the team */ + // This setting does not appear in the settings view, as it is not to be enabled by users outside the team return configuration.get('typescript.enableDiagnosticsTelemetry', false); } From a597b9044f4891ab9c13e736a86ac66b747417ac Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Thu, 24 Aug 2023 11:01:47 +0200 Subject: [PATCH 166/221] disposing the telemetry emitter --- .../src/languageFeatures/diagnostics.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts b/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts index a2a889d1ba2..1f6c21a5d88 100644 --- a/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts +++ b/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts @@ -156,6 +156,7 @@ class DiagnosticsTelemetryManager extends Disposable { private readonly _diagnosticCodesMap = new Map(); private readonly _diagnosticSnapshotsMap = new ResourceMap(uri => uri.toString(), { onCaseInsensitiveFileSystem: false }); private _timeout: NodeJS.Timeout | undefined; + private _telemetryEmitter: NodeJS.Timer | undefined; constructor( private readonly _telemetryReporter: TelemetryReporter, @@ -196,7 +197,7 @@ class DiagnosticsTelemetryManager extends Disposable { } private _registerTelemetryEventEmitter() { - setInterval(() => { + this._telemetryEmitter = setInterval(() => { if (this._diagnosticCodesMap.size > 0) { let diagnosticCodes = ''; this._diagnosticCodesMap.forEach((value, key) => { @@ -222,6 +223,7 @@ class DiagnosticsTelemetryManager extends Disposable { override dispose() { super.dispose(); clearTimeout(this._timeout); + clearInterval(this._telemetryEmitter); } } From 76ab868e1c01ee0c01116bfe50b6d3e7ee098c88 Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Thu, 24 Aug 2023 11:18:24 +0200 Subject: [PATCH 167/221] review comment --- .../browser/stickyScrollController.ts | 1 + .../browser/stickyScrollWidget.ts | 20 +++++++++++++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/vs/editor/contrib/stickyScroll/browser/stickyScrollController.ts b/src/vs/editor/contrib/stickyScroll/browser/stickyScrollController.ts index 5764622526d..53a7aa18f3c 100644 --- a/src/vs/editor/contrib/stickyScroll/browser/stickyScrollController.ts +++ b/src/vs/editor/contrib/stickyScroll/browser/stickyScrollController.ts @@ -430,6 +430,7 @@ export class StickyScrollController extends Disposable implements IEditorContrib private _renderStickyScroll() { const model = this._editor.getModel(); if (!model || model.isTooLargeForTokenization()) { + this._stickyScrollWidget.setState(undefined); return; } const stickyLineVersion = this._stickyLineCandidateProvider.getVersionId(); diff --git a/src/vs/editor/contrib/stickyScroll/browser/stickyScrollWidget.ts b/src/vs/editor/contrib/stickyScroll/browser/stickyScrollWidget.ts index 79e9f479add..607dcb73068 100644 --- a/src/vs/editor/contrib/stickyScroll/browser/stickyScrollWidget.ts +++ b/src/vs/editor/contrib/stickyScroll/browser/stickyScrollWidget.ts @@ -99,9 +99,11 @@ export class StickyScrollWidget extends Disposable implements IOverlayWidget { return this._lineNumbers; } - setState(state: StickyScrollWidgetState): void { - dom.clearNode(this._lineNumbersDomNode); - dom.clearNode(this._linesDomNode); + setState(state: StickyScrollWidgetState | undefined): void { + this._clearStickyWidget(); + if (!state) { + return; + } this._stickyLines = []; const editorLineHeight = this._editor.getOption(EditorOption.lineHeight); const futureWidgetHeight = state.startLineNumbers.length * editorLineHeight + state.lastLineRelativePosition; @@ -129,6 +131,12 @@ export class StickyScrollWidget extends Disposable implements IOverlayWidget { this._rootDomNode.style.width = `${layoutInfo.width - layoutInfo.minimap.minimapCanvasOuterWidth - layoutInfo.verticalScrollbarWidth}px`; } + private _clearStickyWidget() { + dom.clearNode(this._lineNumbersDomNode); + dom.clearNode(this._linesDomNode); + this._rootDomNode.style.display = 'none'; + } + private _renderRootNode(): void { if (!this._editor._getViewModel()) { @@ -145,7 +153,11 @@ export class StickyScrollWidget extends Disposable implements IOverlayWidget { const editorLineHeight = this._editor.getOption(EditorOption.lineHeight); const widgetHeight: number = this._lineNumbers.length * editorLineHeight + this._lastLineRelativePosition; - this._rootDomNode.style.display = widgetHeight > 0 ? 'block' : 'none'; + if (widgetHeight === 0) { + this._clearStickyWidget(); + return; + } + this._rootDomNode.style.display = 'block'; this._lineNumbersDomNode.style.height = `${widgetHeight}px`; this._linesDomNodeScrollable.style.height = `${widgetHeight}px`; this._rootDomNode.style.height = `${widgetHeight}px`; From 65068af4f74187ca06e763f93ddee46d10511002 Mon Sep 17 00:00:00 2001 From: Henning Dieterichs Date: Thu, 24 Aug 2023 11:28:16 +0200 Subject: [PATCH 168/221] Fixes #191144 --- .../browser/parts/editor/editorCommands.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/vs/workbench/browser/parts/editor/editorCommands.ts b/src/vs/workbench/browser/parts/editor/editorCommands.ts index 044bd29da9e..77c8985611a 100644 --- a/src/vs/workbench/browser/parts/editor/editorCommands.ts +++ b/src/vs/workbench/browser/parts/editor/editorCommands.ts @@ -361,6 +361,13 @@ function registerDiffEditorCommands(): void { handler: accessor => navigateInDiffEditor(accessor, true) }); + MenuRegistry.appendMenuItem(MenuId.CommandPalette, { + command: { + id: GOTO_NEXT_CHANGE, + title: { value: localize('compare.nextChange', "Go to Next Change"), original: 'Go to Next Change' }, + } + }); + KeybindingsRegistry.registerCommandAndKeybindingRule({ id: GOTO_PREVIOUS_CHANGE, weight: KeybindingWeight.WorkbenchContrib, @@ -369,6 +376,13 @@ function registerDiffEditorCommands(): void { handler: accessor => navigateInDiffEditor(accessor, false) }); + MenuRegistry.appendMenuItem(MenuId.CommandPalette, { + command: { + id: GOTO_PREVIOUS_CHANGE, + title: { value: localize('compare.previousChange', "Go to Previous Change"), original: 'Go to Previous Change' }, + } + }); + function getActiveTextDiffEditor(accessor: ServicesAccessor): TextDiffEditor | undefined { const editorService = accessor.get(IEditorService); From eac8efd2cd1ff9dfa1bc40e7c24c7cafe20f4523 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Thu, 24 Aug 2023 11:56:40 +0200 Subject: [PATCH 169/221] fix #189339 (#191187) --- src/vs/workbench/browser/parts/views/treeView.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/browser/parts/views/treeView.ts b/src/vs/workbench/browser/parts/views/treeView.ts index c5dc8bf57e3..62ca965951c 100644 --- a/src/vs/workbench/browser/parts/views/treeView.ts +++ b/src/vs/workbench/browser/parts/views/treeView.ts @@ -613,7 +613,7 @@ abstract class AbstractTreeView extends Disposable implements ITreeView { // Pass Focus to Viewer this.tree.domFocus(); - } else if (this.tree) { + } else if (this.tree && this.treeContainer && !this.treeContainer.classList.contains('hide')) { this.tree.domFocus(); } else { this.domNode.focus(); @@ -1017,6 +1017,9 @@ abstract class AbstractTreeView extends Disposable implements ITreeView { this.domNode.setAttribute('tabindex', '0'); } else if (this.treeContainer) { this.treeContainer.classList.remove('hide'); + if (this.domNode === DOM.getActiveElement()) { + this.focus(); + } this.domNode.removeAttribute('tabindex'); } } From 681cd1b481c17b556123f3fafbd4bba8a3d366c3 Mon Sep 17 00:00:00 2001 From: Henning Dieterichs Date: Thu, 24 Aug 2023 12:01:19 +0200 Subject: [PATCH 170/221] Fixes https://github.com/microsoft/vscode/issues/187889 --- .../inlineCompletions/browser/inlineCompletionsController.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/editor/contrib/inlineCompletions/browser/inlineCompletionsController.ts b/src/vs/editor/contrib/inlineCompletions/browser/inlineCompletionsController.ts index 51b2d4fc562..094393e32c5 100644 --- a/src/vs/editor/contrib/inlineCompletions/browser/inlineCompletionsController.ts +++ b/src/vs/editor/contrib/inlineCompletions/browser/inlineCompletionsController.ts @@ -117,7 +117,7 @@ export class InlineCompletionsController extends Disposable { this._register(editor.onDidChangeCursorPosition(e => transaction(tx => { /** @description onDidChangeCursorPosition */ this.updateObservables(tx, VersionIdChangeReason.Other); - if (e.reason === CursorChangeReason.Explicit) { + if (e.reason === CursorChangeReason.Explicit || e.source === 'api') { this.model.get()?.stop(tx); } }))); From 2d0cb77ab8b4950f9331dbdbf71aacc305c91b9f Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 24 Aug 2023 12:45:53 +0200 Subject: [PATCH 171/221] voice - support inline chat --- .../browser/actions/chatExecuteActions.ts | 2 +- .../actions/chatVoiceInputActions.ts | 411 ++++++++++++------ .../browser/inlineChatController.ts | 14 +- .../workbenchVoiceRecognitionService.ts | 1 + 4 files changed, 289 insertions(+), 139 deletions(-) diff --git a/src/vs/workbench/contrib/chat/browser/actions/chatExecuteActions.ts b/src/vs/workbench/contrib/chat/browser/actions/chatExecuteActions.ts index 7f639db3aeb..07776d570a6 100644 --- a/src/vs/workbench/contrib/chat/browser/actions/chatExecuteActions.ts +++ b/src/vs/workbench/contrib/chat/browser/actions/chatExecuteActions.ts @@ -17,7 +17,7 @@ export interface IChatExecuteActionContext { inputValue?: string; } -function isExecuteActionContext(thing: unknown): thing is IChatExecuteActionContext { +export function isExecuteActionContext(thing: unknown): thing is IChatExecuteActionContext { return typeof thing === 'object' && thing !== null && 'widget' in thing; } diff --git a/src/vs/workbench/contrib/chat/electron-sandbox/actions/chatVoiceInputActions.ts b/src/vs/workbench/contrib/chat/electron-sandbox/actions/chatVoiceInputActions.ts index f4d874d252d..8bcc0fd7632 100644 --- a/src/vs/workbench/contrib/chat/electron-sandbox/actions/chatVoiceInputActions.ts +++ b/src/vs/workbench/contrib/chat/electron-sandbox/actions/chatVoiceInputActions.ts @@ -7,7 +7,7 @@ import { Event } from 'vs/base/common/event'; import { firstOrDefault } from 'vs/base/common/arrays'; import { CancellationTokenSource } from 'vs/base/common/cancellation'; import { Codicon } from 'vs/base/common/codicons'; -import { DisposableStore, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; +import { Disposable, DisposableStore, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { equalsIgnoreCase } from 'vs/base/common/strings'; import { ServicesAccessor } from 'vs/editor/browser/editorExtensions'; import { localize } from 'vs/nls'; @@ -16,69 +16,98 @@ import { IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { spinningLoading } from 'vs/platform/theme/common/iconRegistry'; import { CHAT_CATEGORY } from 'vs/workbench/contrib/chat/browser/actions/chatActions'; -import { IChatWidget, IChatWidgetService, IQuickChatService } from 'vs/workbench/contrib/chat/browser/chat'; +import { IChatWidgetService, IQuickChatService } from 'vs/workbench/contrib/chat/browser/chat'; import { IChatService } from 'vs/workbench/contrib/chat/common/chatService'; import { IWorkbenchVoiceRecognitionService } from 'vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService'; +import { MENU_INLINE_CHAT_WIDGET } from 'vs/workbench/contrib/inlineChat/common/inlineChat'; +import { CONTEXT_PROVIDER_EXISTS } from 'vs/workbench/contrib/chat/common/chatContextKeys'; +import { InlineChatController } from 'vs/workbench/contrib/inlineChat/browser/inlineChatController'; +import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; +import { getCodeEditor } from 'vs/editor/browser/editorBrowser'; +import { isExecuteActionContext } from 'vs/workbench/contrib/chat/browser/actions/chatExecuteActions'; -const CONTEXT_CHAT_VOICE_INPUT_GETTING_READY = new RawContextKey('chatVoiceInputGettingReady', false, { type: 'boolean', description: localize('chatVoiceInputGettingReady', "True when there is voice input for chat getting ready.") }); -const CONTEXT_CHAT_VOICE_INPUT_IN_PROGRESS = new RawContextKey('chatVoiceInputInProgress', false, { type: 'boolean', description: localize('chatVoiceInputInProgress', "True when there is voice input for chat in progress.") }); +const CONTEXT_VOICE_CHAT_GETTING_READY = new RawContextKey('voiceChatGettingReady', false, { type: 'boolean', description: localize('voiceChatGettingReady', "True when there is voice input for chat getting ready.") }); +const CONTEXT_VOICE_CHAT_IN_PROGRESS = new RawContextKey('voiceChatInProgress', false, { type: 'boolean', description: localize('voiceChatInProgress', "True when there is voice input for chat in progress.") }); -interface IChatVoiceInputActionContext { - readonly widget: IChatWidget; - readonly inputValue?: string; +interface IVoiceChatSessionController { + + readonly onDidAcceptInput: Event; + + focusInput(): void; + acceptInput(): void; + updateInput(text: string): void; } -function isVoiceInputActionContext(thing: unknown): thing is IChatVoiceInputActionContext { - return typeof thing === 'object' && thing !== null && 'widget' in thing; -} - -class ChatVoiceInputSession { - - private static instance: ChatVoiceInputSession | undefined = undefined; - static getInstance(instantiationService: IInstantiationService): ChatVoiceInputSession { - if (!ChatVoiceInputSession.instance) { - ChatVoiceInputSession.instance = instantiationService.createInstance(ChatVoiceInputSession); - } - - return ChatVoiceInputSession.instance; +function getController(controller: InlineChatController): IVoiceChatSessionController; +function getController(context: unknown): IVoiceChatSessionController | undefined; +function getController(context: unknown): IVoiceChatSessionController | undefined { + if (context instanceof InlineChatController) { + return { + onDidAcceptInput: context.onDidAcceptInput, + focusInput: () => context.focus(), + acceptInput: () => context.acceptInput(), + updateInput: text => context.updateInput(text) + }; } - private chatVoiceInputInProgressKey = CONTEXT_CHAT_VOICE_INPUT_IN_PROGRESS.bindTo(this.contextKeyService); - private chatVoiceInputGettingReadyKey = CONTEXT_CHAT_VOICE_INPUT_GETTING_READY.bindTo(this.contextKeyService); + if (isExecuteActionContext(context)) { + return context.widget; + } - private currentChatVoiceInputSession: DisposableStore | undefined = undefined; + return undefined; +} + +class VoiceChatSession { + + private static instance: VoiceChatSession | undefined = undefined; + static getInstance(instantiationService: IInstantiationService): VoiceChatSession { + if (!VoiceChatSession.instance) { + VoiceChatSession.instance = instantiationService.createInstance(VoiceChatSession); + } + + return VoiceChatSession.instance; + } + + private voiceChatInProgressKey = CONTEXT_VOICE_CHAT_IN_PROGRESS.bindTo(this.contextKeyService); + private voiceChatGettingReadyKey = CONTEXT_VOICE_CHAT_GETTING_READY.bindTo(this.contextKeyService); + + private currentVoiceChatSession: DisposableStore | undefined = undefined; + private voiceChatSessionIds = 0; constructor( @IContextKeyService private readonly contextKeyService: IContextKeyService, @IWorkbenchVoiceRecognitionService private readonly voiceRecognitionService: IWorkbenchVoiceRecognitionService ) { } - async start(context: IChatVoiceInputActionContext, disposables?: IDisposable[]): Promise { + async start(context: IVoiceChatSessionController): Promise { this.stop(); - this.chatVoiceInputGettingReadyKey.set(true); - this.currentChatVoiceInputSession = new DisposableStore(); - for (const disposable of disposables ?? []) { - this.currentChatVoiceInputSession.add(disposable); - } + this.voiceChatGettingReadyKey.set(true); + this.currentVoiceChatSession = new DisposableStore(); const cts = new CancellationTokenSource(); - this.currentChatVoiceInputSession.add(toDisposable(() => cts.dispose(true))); + this.currentVoiceChatSession.add(toDisposable(() => cts.dispose(true))); - context.widget.focusInput(); + context.focusInput(); const onDidTranscribe = await this.voiceRecognitionService.transcribe(cts.token); if (cts.token.isCancellationRequested) { - return; + return Disposable.None; } - this.chatVoiceInputGettingReadyKey.set(false); - this.chatVoiceInputInProgressKey.set(true); + const voiceChatSessionId = this.voiceChatSessionIds++; + + this.voiceChatGettingReadyKey.set(false); + this.voiceChatInProgressKey.set(true); let lastText: string | undefined = undefined; let lastTextSimilarCount = 0; - this.currentChatVoiceInputSession.add(onDidTranscribe(text => { + this.currentVoiceChatSession.add(onDidTranscribe(text => { + if (!text && lastText) { + text = lastText; + } + if (text) { if (lastText && this.isSimilarTranscription(text, lastText)) { lastTextSimilarCount++; @@ -88,17 +117,23 @@ class ChatVoiceInputSession { } if (lastTextSimilarCount >= 2) { - context.widget.acceptInput(); + context.acceptInput(); } else { - context.widget.updateInput(text); + context.updateInput(text); } } })); - this.currentChatVoiceInputSession.add(context.widget.onDidAcceptInput(() => { + this.currentVoiceChatSession.add(context.onDidAcceptInput(() => { this.stop(); })); + + return toDisposable(() => { + if (this.voiceChatSessionIds === voiceChatSessionId) { + this.stop(); + } + }); } private isSimilarTranscription(textA: string, textB: string): boolean { @@ -116,131 +151,235 @@ class ChatVoiceInputSession { } stop(): void { - if (!this.currentChatVoiceInputSession) { + if (!this.currentVoiceChatSession) { return; } - this.currentChatVoiceInputSession.dispose(); - this.currentChatVoiceInputSession = undefined; + this.currentVoiceChatSession.dispose(); + this.currentVoiceChatSession = undefined; - this.chatVoiceInputGettingReadyKey.set(false); - this.chatVoiceInputInProgressKey.set(false); + this.voiceChatGettingReadyKey.set(false); + this.voiceChatInProgressKey.set(false); } } -class StartChatVoiceInputAction extends Action2 { +class VoiceChatInChatViewAction extends Action2 { - static readonly ID = 'workbench.action.chat.startVoiceInput'; + static readonly ID = 'workbench.action.chat.voiceChatInChatView'; constructor() { super({ - id: StartChatVoiceInputAction.ID, + id: VoiceChatInChatViewAction.ID, title: { - value: localize('interactive.voiceInput.label', "Start Voice Input"), - original: 'Start Voice Input' - }, - category: CHAT_CATEGORY, - f1: true, - icon: Codicon.record, - precondition: CONTEXT_CHAT_VOICE_INPUT_GETTING_READY.negate(), - menu: { - id: MenuId.ChatExecute, - when: CONTEXT_CHAT_VOICE_INPUT_IN_PROGRESS.negate(), - group: 'navigation', - order: -1 - } - }); - } - - async run(accessor: ServicesAccessor, ...args: any[]): Promise { - const chatWidgetService = accessor.get(IChatWidgetService); - const chatService = accessor.get(IChatService); - const instantiationService = accessor.get(IInstantiationService); - - let context = args[0]; - if (!isVoiceInputActionContext(context)) { - if (chatWidgetService.lastFocusedWidget?.hasInputFocus()) { - context = { widget: chatWidgetService.lastFocusedWidget }; - } else { - const provider = firstOrDefault(chatService.getProviderInfos()); - if (provider) { - context = { widget: await chatWidgetService.revealViewForProvider(provider.id) }; - } - } - } - - if (!isVoiceInputActionContext(context)) { - return; - } - - ChatVoiceInputSession.getInstance(instantiationService).start(context); - } -} - -class StopChatVoiceInputAction extends Action2 { - - static readonly ID = 'workbench.action.chat.stopVoiceInput'; - - constructor() { - super({ - id: StopChatVoiceInputAction.ID, - title: { - value: localize('interactive.stopVoiceInput.label', "Stop Voice Input"), - original: 'Stop Voice Input' - }, - category: CHAT_CATEGORY, - f1: true, - precondition: CONTEXT_CHAT_VOICE_INPUT_IN_PROGRESS, - icon: spinningLoading, - menu: { - id: MenuId.ChatExecute, - when: CONTEXT_CHAT_VOICE_INPUT_IN_PROGRESS, - group: 'navigation', - order: -1 - } - }); - } - - run(accessor: ServicesAccessor): void { - ChatVoiceInputSession.getInstance(accessor.get(IInstantiationService)).stop(); - } -} - -class VoiceQuickChatAction extends Action2 { - - static readonly ID = 'workbench.action.chat.voiceQuickChat'; - - constructor() { - super({ - id: VoiceQuickChatAction.ID, - title: { - value: localize('interactive.voiceQuickChat.label', "Quick Chat with Voice Input"), - original: 'Quick Chat with Voice Input' + value: localize('workbench.action.chat.voiceChatInView.label', "Voice Chat in Chat View"), + original: 'Voice Chat in Chat View' }, category: CHAT_CATEGORY, + precondition: CONTEXT_PROVIDER_EXISTS, f1: true }); } - run(accessor: ServicesAccessor): void { + async run(accessor: ServicesAccessor): Promise { + const chatWidgetService = accessor.get(IChatWidgetService); + const chatService = accessor.get(IChatService); + const instantiationService = accessor.get(IInstantiationService); + + const provider = firstOrDefault(chatService.getProviderInfos()); + if (provider) { + const controller = await chatWidgetService.revealViewForProvider(provider.id); + if (controller) { + VoiceChatSession.getInstance(instantiationService).start(controller); + } + } + } +} + +class InlineVoiceChatAction extends Action2 { + + static readonly ID = 'workbench.action.chat.inlineVoiceChat'; + + constructor() { + super({ + id: InlineVoiceChatAction.ID, + title: { + value: localize('workbench.action.chat.inlineVoiceChat', "Inline Voice Chat"), + original: 'Inline Voice Chat' + }, + category: CHAT_CATEGORY, + precondition: CONTEXT_PROVIDER_EXISTS, + f1: true + }); + } + + async run(accessor: ServicesAccessor): Promise { + const editorService = accessor.get(IEditorService); + const instantiationService = accessor.get(IInstantiationService); + + const activeCodeEditor = getCodeEditor(editorService.activeTextEditorControl); + if (!activeCodeEditor) { + return; + } + + const controller = InlineChatController.get(activeCodeEditor); + if (!controller) { + return; + } + + const inlineChatSession = controller.run(); + + const disposable = await VoiceChatSession.getInstance(instantiationService).start(getController(controller)); + + inlineChatSession.finally(() => disposable.dispose()); + } +} + +class QuickVoiceChatAction extends Action2 { + + static readonly ID = 'workbench.action.chat.quickVoiceChat'; + + constructor() { + super({ + id: QuickVoiceChatAction.ID, + title: { + value: localize('workbench.action.chat.quickVoiceChat.label', "Quick Voice Chat"), + original: 'Quick Voice Chat' + }, + category: CHAT_CATEGORY, + precondition: CONTEXT_PROVIDER_EXISTS, + f1: true + }); + } + + async run(accessor: ServicesAccessor): Promise { const quickChatService = accessor.get(IQuickChatService); const chatWidgetService = accessor.get(IChatWidgetService); const instantiationService = accessor.get(IInstantiationService); quickChatService.open(); - const disposables: IDisposable[] = []; - Event.once(quickChatService.onDidClose)(() => ChatVoiceInputSession.getInstance(instantiationService).stop(), undefined, disposables); - - const widget = chatWidgetService.lastFocusedWidget; - if (widget) { - ChatVoiceInputSession.getInstance(accessor.get(IInstantiationService)).start({ widget }, disposables); + const controller = chatWidgetService.lastFocusedWidget; + if (controller) { + const disposable = await VoiceChatSession.getInstance(instantiationService).start(controller); + Event.once(quickChatService.onDidClose)(() => disposable.dispose()); } } } +class StartVoiceChatAction extends Action2 { + + static readonly ID = 'workbench.action.chat.startVoiceChat'; + + constructor() { + super({ + id: StartVoiceChatAction.ID, + title: { + value: localize('workbench.action.chat.startVoiceChat', "Start Voice Chat"), + original: 'Start Voice Chat' + }, + icon: Codicon.record, + precondition: CONTEXT_VOICE_CHAT_GETTING_READY.negate(), + menu: [{ + id: MenuId.ChatExecute, + when: CONTEXT_VOICE_CHAT_IN_PROGRESS.negate(), + group: 'navigation', + order: -1 + }, { + id: MENU_INLINE_CHAT_WIDGET, + when: CONTEXT_VOICE_CHAT_IN_PROGRESS.negate(), + group: 'main', + order: -1 + }] + }); + } + + async run(accessor: ServicesAccessor, context: unknown): Promise { + const editorService = accessor.get(IEditorService); + const chatWidgetService = accessor.get(IChatWidgetService); + const chatService = accessor.get(IChatService); + const instantiationService = accessor.get(IInstantiationService); + + let controller = getController(context); + if (!controller) { + + // Without a controller, this action potentially executed from + // a global keybinding, and thus we have to find the chat + // input that is currently focussed, or fallback to opening one + + // 1.) a chat input widget has focus + { + if (chatWidgetService.lastFocusedWidget?.hasInputFocus()) { + controller = chatWidgetService.lastFocusedWidget; + } + } + + // 2.) a inline chat input widget has focus + { + const activeCodeEditor = getCodeEditor(editorService.activeTextEditorControl); + if (activeCodeEditor) { + const chatInput = InlineChatController.get(activeCodeEditor); + if (chatInput?.hasFocus()) { + controller = getController(chatInput); + } + } + } + + // 3.) open a chat view + { + const provider = firstOrDefault(chatService.getProviderInfos()); + if (provider) { + controller = await chatWidgetService.revealViewForProvider(provider.id); + } + } + } + + if (!controller) { + return; + } + + VoiceChatSession.getInstance(instantiationService).start(controller); + } +} + +class StopVoiceChatAction extends Action2 { + + static readonly ID = 'workbench.action.chat.stopVoiceChat'; + + constructor() { + super({ + id: StopVoiceChatAction.ID, + title: { + value: localize('workbench.action.chat.stopVoiceChat.label', "Stop Voice Chat"), + original: 'Stop Voice Chat' + }, + category: CHAT_CATEGORY, + f1: true, + precondition: CONTEXT_VOICE_CHAT_IN_PROGRESS, + icon: spinningLoading, + menu: [{ + id: MenuId.ChatExecute, + when: CONTEXT_VOICE_CHAT_IN_PROGRESS, + group: 'navigation', + order: -1 + }, { + id: MENU_INLINE_CHAT_WIDGET, + when: CONTEXT_VOICE_CHAT_IN_PROGRESS, + group: 'main', + order: -1 + }] + }); + } + + run(accessor: ServicesAccessor): void { + VoiceChatSession.getInstance(accessor.get(IInstantiationService)).stop(); + } +} + export function registerChatVoiceInputActions() { - registerAction2(StartChatVoiceInputAction); - registerAction2(StopChatVoiceInputAction); - registerAction2(VoiceQuickChatAction); + registerAction2(VoiceChatInChatViewAction); + registerAction2(QuickVoiceChatAction); + registerAction2(InlineVoiceChatAction); + + registerAction2(StartVoiceChatAction); + registerAction2(StopVoiceChatAction); } diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts index f91de7e3ee8..023fee9cfd2 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts @@ -100,6 +100,8 @@ export class InlineChatController implements IEditorContribution { private _messages = this._store.add(new Emitter()); + readonly onDidAcceptInput = Event.filter(this._messages.event, m => m === Message.ACCEPT_INPUT, this._store); + private readonly _sessionStore: DisposableStore = this._store.add(new DisposableStore()); private readonly _stashedSession: MutableDisposable = this._store.add(new MutableDisposable()); private _activeSession?: Session; @@ -395,8 +397,7 @@ export class InlineChatController implements IEditorContribution { this._zone.value.widget.placeholder = this._getPlaceholderText(); if (options.message) { - this._zone.value.widget.value = options.message; - this._zone.value.widget.selectAll(); + this.updateInput(options.message); aria.alert(options.message); delete options.message; } @@ -758,6 +759,11 @@ export class InlineChatController implements IEditorContribution { this._messages.fire(Message.ACCEPT_INPUT); } + updateInput(text: string): void { + this._zone.value.widget.value = text; + this._zone.value.widget.selectAll(); + } + regenerate(): void { this._messages.fire(Message.RERUN_INPUT); } @@ -780,6 +786,10 @@ export class InlineChatController implements IEditorContribution { this._zone.value.widget.focus(); } + hasFocus(): boolean { + return this._zone.value.widget.hasFocus(); + } + populateHistory(up: boolean) { const len = InlineChatController._promptHistory.length; if (len === 0) { diff --git a/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts b/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts index 3a10c4afa7b..5688961771f 100644 --- a/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts +++ b/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts @@ -64,6 +64,7 @@ class VoiceTranscriptionWorkletNode extends AudioWorkletNode { // TODO@voice // - add native module test to ensure module loads +// - allow to cancel voice recording from window progress export class WorkbenchVoiceRecognitionService implements IWorkbenchVoiceRecognitionService { declare readonly _serviceBrand: undefined; From 08b1b5bea836e4e403b9927a3c54593f22790c3e Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 24 Aug 2023 12:55:48 +0200 Subject: [PATCH 172/221] voice - allow to cancel from global progress --- .../actions/chatVoiceInputActions.ts | 4 +- .../workbenchVoiceRecognitionService.ts | 46 +++++++++++++------ 2 files changed, 34 insertions(+), 16 deletions(-) diff --git a/src/vs/workbench/contrib/chat/electron-sandbox/actions/chatVoiceInputActions.ts b/src/vs/workbench/contrib/chat/electron-sandbox/actions/chatVoiceInputActions.ts index 8bcc0fd7632..01d8c65cff1 100644 --- a/src/vs/workbench/contrib/chat/electron-sandbox/actions/chatVoiceInputActions.ts +++ b/src/vs/workbench/contrib/chat/electron-sandbox/actions/chatVoiceInputActions.ts @@ -90,7 +90,9 @@ class VoiceChatSession { context.focusInput(); - const onDidTranscribe = await this.voiceRecognitionService.transcribe(cts.token); + const onDidTranscribe = await this.voiceRecognitionService.transcribe(cts.token, { + onDidCancel: () => this.stop() + }); if (cts.token.isCancellationRequested) { return Disposable.None; } diff --git a/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts b/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts index 5688961771f..c1863701239 100644 --- a/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts +++ b/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { localize } from 'vs/nls'; -import { CancellationToken } from 'vs/base/common/cancellation'; +import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation'; import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { Emitter, Event } from 'vs/base/common/event'; @@ -16,17 +16,26 @@ import { INotificationService } from 'vs/platform/notification/common/notificati export const IWorkbenchVoiceRecognitionService = createDecorator('workbenchVoiceRecognitionService'); +export interface IWorkbenchVoiceRecognitionOptions { + + /** + * Optional event that is fired when the user cancels the voice recognition. + */ + readonly onDidCancel?: () => void; +} + export interface IWorkbenchVoiceRecognitionService { readonly _serviceBrand: undefined; /** - * Starts listening to the microphone transcribing the voice to text. + * Starts listening to the microphone transcribing the voice to text. Microphone + * recording starts when the returned promise is resolved. * * @param cancellation a cancellation token to stop transcribing and * listening to the microphone. */ - transcribe(cancellation: CancellationToken): Promise>; + transcribe(cancellation: CancellationToken, options?: IWorkbenchVoiceRecognitionOptions): Promise>; } class VoiceTranscriptionWorkletNode extends AudioWorkletNode { @@ -64,7 +73,6 @@ class VoiceTranscriptionWorkletNode extends AudioWorkletNode { // TODO@voice // - add native module test to ensure module loads -// - allow to cancel voice recording from window progress export class WorkbenchVoiceRecognitionService implements IWorkbenchVoiceRecognitionService { declare readonly _serviceBrand: undefined; @@ -79,22 +87,28 @@ export class WorkbenchVoiceRecognitionService implements IWorkbenchVoiceRecognit @INotificationService private readonly notificationService: INotificationService ) { } - async transcribe(cancellation: CancellationToken): Promise> { - const onDidTranscribe = new Emitter(); - cancellation.onCancellationRequested(() => onDidTranscribe.dispose()); + async transcribe(cancellation: CancellationToken, options?: IWorkbenchVoiceRecognitionOptions): Promise> { + const cts = new CancellationTokenSource(cancellation); - await this.doTranscribe(onDidTranscribe, cancellation); + const onDidTranscribe = new Emitter(); + cts.token.onCancellationRequested(() => { + onDidTranscribe.dispose(); + options?.onDidCancel?.(); + }); + + await this.doTranscribe(onDidTranscribe, cts); return onDidTranscribe.event; } - private doTranscribe(onDidTranscribe: Emitter, token: CancellationToken): Promise { + private doTranscribe(onDidTranscribe: Emitter, cts: CancellationTokenSource): Promise { const recordingReady = new DeferredPromise(); - token.onCancellationRequested(() => recordingReady.complete()); + cts.token.onCancellationRequested(() => recordingReady.complete()); this.progressService.withProgress({ location: ProgressLocation.Window, title: localize('voiceTranscription', "Voice Transcription"), + cancellable: true }, async progress => { const recordingDone = new DeferredPromise(); try { @@ -110,7 +124,7 @@ export class WorkbenchVoiceRecognitionService implements IWorkbenchVoiceRecognit } }); - if (token.isCancellationRequested) { + if (cts.token.isCancellationRequested) { return; } @@ -121,7 +135,7 @@ export class WorkbenchVoiceRecognitionService implements IWorkbenchVoiceRecognit const microphoneSource = audioContext.createMediaStreamSource(microphoneDevice); - token.onCancellationRequested(() => { + cts.token.onCancellationRequested(() => { try { for (const track of microphoneDevice.getTracks()) { track.stop(); @@ -136,7 +150,7 @@ export class WorkbenchVoiceRecognitionService implements IWorkbenchVoiceRecognit await audioContext.audioWorklet.addModule(FileAccess.asBrowserUri('vs/workbench/services/voiceRecognition/electron-sandbox/voiceTranscriptionWorklet.js').toString(true)); - if (token.isCancellationRequested) { + if (cts.token.isCancellationRequested) { return; } @@ -144,9 +158,9 @@ export class WorkbenchVoiceRecognitionService implements IWorkbenchVoiceRecognit channelCount: WorkbenchVoiceRecognitionService.AUDIO_CHANNELS, channelCountMode: 'explicit' }, onDidTranscribe, this.sharedProcessService); - await voiceTranscriptionTarget.start(token); + await voiceTranscriptionTarget.start(cts.token); - if (token.isCancellationRequested) { + if (cts.token.isCancellationRequested) { return; } @@ -162,6 +176,8 @@ export class WorkbenchVoiceRecognitionService implements IWorkbenchVoiceRecognit recordingReady.error(error); recordingDone.error(error); } + }, () => { + cts.cancel(); }); return recordingReady.p; From 518f1dcff7b5167104a5c57b0cb78978b5576e83 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 24 Aug 2023 13:04:10 +0200 Subject: [PATCH 173/221] voice - prefer quick chat as fallback --- .../actions/chatVoiceInputActions.ts | 22 ++++++++----------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/src/vs/workbench/contrib/chat/electron-sandbox/actions/chatVoiceInputActions.ts b/src/vs/workbench/contrib/chat/electron-sandbox/actions/chatVoiceInputActions.ts index 01d8c65cff1..91e0e6490c5 100644 --- a/src/vs/workbench/contrib/chat/electron-sandbox/actions/chatVoiceInputActions.ts +++ b/src/vs/workbench/contrib/chat/electron-sandbox/actions/chatVoiceInputActions.ts @@ -25,6 +25,7 @@ import { InlineChatController } from 'vs/workbench/contrib/inlineChat/browser/in import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { getCodeEditor } from 'vs/editor/browser/editorBrowser'; import { isExecuteActionContext } from 'vs/workbench/contrib/chat/browser/actions/chatExecuteActions'; +import { ICommandService } from 'vs/platform/commands/common/commands'; const CONTEXT_VOICE_CHAT_GETTING_READY = new RawContextKey('voiceChatGettingReady', false, { type: 'boolean', description: localize('voiceChatGettingReady', "True when there is voice input for chat getting ready.") }); const CONTEXT_VOICE_CHAT_IN_PROGRESS = new RawContextKey('voiceChatInProgress', false, { type: 'boolean', description: localize('voiceChatInProgress', "True when there is voice input for chat in progress.") }); @@ -298,25 +299,23 @@ class StartVoiceChatAction extends Action2 { async run(accessor: ServicesAccessor, context: unknown): Promise { const editorService = accessor.get(IEditorService); const chatWidgetService = accessor.get(IChatWidgetService); - const chatService = accessor.get(IChatService); const instantiationService = accessor.get(IInstantiationService); + const commandService = accessor.get(ICommandService); let controller = getController(context); if (!controller) { // Without a controller, this action potentially executed from // a global keybinding, and thus we have to find the chat - // input that is currently focussed, or fallback to opening one + // input that is currently focussed, or have a fallback // 1.) a chat input widget has focus - { - if (chatWidgetService.lastFocusedWidget?.hasInputFocus()) { - controller = chatWidgetService.lastFocusedWidget; - } + if (chatWidgetService.lastFocusedWidget?.hasInputFocus()) { + controller = chatWidgetService.lastFocusedWidget; } // 2.) a inline chat input widget has focus - { + if (!controller) { const activeCodeEditor = getCodeEditor(editorService.activeTextEditorControl); if (activeCodeEditor) { const chatInput = InlineChatController.get(activeCodeEditor); @@ -326,12 +325,9 @@ class StartVoiceChatAction extends Action2 { } } - // 3.) open a chat view - { - const provider = firstOrDefault(chatService.getProviderInfos()); - if (provider) { - controller = await chatWidgetService.revealViewForProvider(provider.id); - } + // 3.) open a quick chat view + if (!controller) { + return commandService.executeCommand(QuickVoiceChatAction.ID); } } From 92b1178b552431333feba64a270a514055e96ccc Mon Sep 17 00:00:00 2001 From: Henning Dieterichs Date: Thu, 24 Aug 2023 12:37:34 +0200 Subject: [PATCH 174/221] Fixes #190325 --- .../diffEditorWidget2/accessibleDiffViewer.ts | 5 +-- src/vs/editor/common/core/offsetRange.ts | 34 +++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/vs/editor/browser/widget/diffEditorWidget2/accessibleDiffViewer.ts b/src/vs/editor/browser/widget/diffEditorWidget2/accessibleDiffViewer.ts index d66333e1aec..32f45d85186 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget2/accessibleDiffViewer.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget2/accessibleDiffViewer.ts @@ -18,6 +18,7 @@ import { applyStyle } from 'vs/editor/browser/widget/diffEditorWidget2/utils'; import { DiffReview } from 'vs/editor/browser/widget/diffReview'; import { EditorFontLigatures, EditorOption, IComputedEditorOptions } from 'vs/editor/common/config/editorOptions'; import { LineRange } from 'vs/editor/common/core/lineRange'; +import { OffsetRange } from 'vs/editor/common/core/offsetRange'; import { Position } from 'vs/editor/common/core/position'; import { Range } from 'vs/editor/common/core/range'; import { LineRangeMapping, SimpleLineRangeMapping } from 'vs/editor/common/diff/linesDiffComputer'; @@ -163,7 +164,7 @@ class ViewModel extends Disposable { const groups = this.groups.get(); if (!groups || groups.length <= 1) { return; } subtransaction(tx, tx => { - this._currentGroupIdx.set((this._currentGroupIdx.get() + groups.length + delta) % groups.length, tx); + this._currentGroupIdx.set(OffsetRange.ofLength(groups.length).clipCyclic(this._currentGroupIdx.get() + delta), tx); this._currentElementIdx.set(0, tx); }); } @@ -175,7 +176,7 @@ class ViewModel extends Disposable { const group = this.currentGroup.get(); if (!group || group.lines.length <= 1) { return; } transaction(tx => { - this._currentElementIdx.set((this._currentElementIdx.get() + group.lines.length + delta) % group.lines.length, tx); + this._currentElementIdx.set(OffsetRange.ofLength(group.lines.length).clip(this._currentElementIdx.get() + delta), tx); }); } diff --git a/src/vs/editor/common/core/offsetRange.ts b/src/vs/editor/common/core/offsetRange.ts index d4129b1c532..27e60bca2df 100644 --- a/src/vs/editor/common/core/offsetRange.ts +++ b/src/vs/editor/common/core/offsetRange.ts @@ -34,6 +34,10 @@ export class OffsetRange { return new OffsetRange(start, endExclusive); } + public static ofLength(length: number): OffsetRange { + return new OffsetRange(0, length); + } + constructor(public readonly start: number, public readonly endExclusive: number) { if (start > endExclusive) { throw new BugIndicatingError(`Invalid range: ${this.toString()}`); @@ -102,6 +106,36 @@ export class OffsetRange { public slice(arr: T[]): T[] { return arr.slice(this.start, this.endExclusive); } + + /** + * Returns the given value if it is contained in this instance, otherwise the closest value that is contained. + * The range must not be empty. + */ + public clip(value: number): number { + if (this.isEmpty) { + throw new BugIndicatingError(`Invalid clipping range: ${this.toString()}`); + } + return Math.max(this.start, Math.min(this.endExclusive - 1, value)); + } + + /** + * Returns `r := value + k * length` such that `r` is contained in this range. + * The range must not be empty. + * + * E.g. `[5, 10).clipCyclic(10) === 5`, `[5, 10).clipCyclic(11) === 6` and `[5, 10).clipCyclic(4) === 9`. + */ + public clipCyclic(value: number): number { + if (this.isEmpty) { + throw new BugIndicatingError(`Invalid clipping range: ${this.toString()}`); + } + if (value < this.start) { + return this.endExclusive - ((this.start - value) % this.length); + } + if (value >= this.endExclusive) { + return this.start + ((value - this.start) % this.length); + } + return value; + } } export class OffsetRangeSet { From 7b7f33106a88a315be47f4db1cd5358833f1a371 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Thu, 24 Aug 2023 14:16:31 +0200 Subject: [PATCH 175/221] fix #189872 (#191206) --- .../contrib/extensions/browser/fileBasedRecommendations.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/extensions/browser/fileBasedRecommendations.ts b/src/vs/workbench/contrib/extensions/browser/fileBasedRecommendations.ts index b3417372e48..b886e417338 100644 --- a/src/vs/workbench/contrib/extensions/browser/fileBasedRecommendations.ts +++ b/src/vs/workbench/contrib/extensions/browser/fileBasedRecommendations.ts @@ -281,7 +281,7 @@ export class FileBasedRecommendations extends ExtensionRecommendations { const language = model.getLanguageId(); const languageName = this.languageService.getLanguageName(language); if (importantRecommendations.size && - this.promptRecommendedExtensionForFileType(languageName && isImportantRecommendationForLanguage && language !== PLAINTEXT_LANGUAGE_ID ? localize('languageName', "{0} language", languageName) : basename(uri), language, [...importantRecommendations])) { + this.promptRecommendedExtensionForFileType(languageName && isImportantRecommendationForLanguage && language !== PLAINTEXT_LANGUAGE_ID ? localize('languageName', "the {0} language", languageName) : basename(uri), language, [...importantRecommendations])) { return; } } From 1e8ccdc0ff61b62177be63644c5526252b961e9b Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Thu, 24 Aug 2023 14:25:39 +0200 Subject: [PATCH 176/221] #189481 scope to web (#191204) --- .../browser/userDataSyncWorkbenchService.ts | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/vs/workbench/services/userDataSync/browser/userDataSyncWorkbenchService.ts b/src/vs/workbench/services/userDataSync/browser/userDataSyncWorkbenchService.ts index 0668f9e3b6a..d509a21c76c 100644 --- a/src/vs/workbench/services/userDataSync/browser/userDataSyncWorkbenchService.ts +++ b/src/vs/workbench/services/userDataSync/browser/userDataSyncWorkbenchService.ts @@ -171,17 +171,19 @@ export class UserDataSyncWorkbenchService extends Disposable implements IUserDat } private async initialize(): Promise { - const authenticationSession = await getCurrentAuthenticationSessionInfo(this.credentialsService, this.secretStorageService, this.productService); - if (this.currentSessionId === undefined && authenticationSession?.id) { - if (this.environmentService.options?.settingsSyncOptions?.authenticationProvider && this.environmentService.options.settingsSyncOptions.enabled) { - this.currentSessionId = authenticationSession.id; - } + if (isWeb) { + const authenticationSession = await getCurrentAuthenticationSessionInfo(this.credentialsService, this.secretStorageService, this.productService); + if (this.currentSessionId === undefined && authenticationSession?.id) { + if (this.environmentService.options?.settingsSyncOptions?.authenticationProvider && this.environmentService.options.settingsSyncOptions.enabled) { + this.currentSessionId = authenticationSession.id; + } - // Backward compatibility - else if (this.useWorkbenchSessionId) { - this.currentSessionId = authenticationSession.id; + // Backward compatibility + else if (this.useWorkbenchSessionId) { + this.currentSessionId = authenticationSession.id; + } + this.useWorkbenchSessionId = false; } - this.useWorkbenchSessionId = false; } await this.update(); From cafcb59c16b5fcb2ae2db76cea0ba2596df8b7db Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Thu, 24 Aug 2023 14:32:29 +0200 Subject: [PATCH 177/221] fix #190228 (#191207) --- .../workbench/contrib/extensions/browser/extensionEditor.ts | 6 ++---- .../contrib/extensions/browser/media/extensionEditor.css | 4 ---- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/src/vs/workbench/contrib/extensions/browser/extensionEditor.ts b/src/vs/workbench/contrib/extensions/browser/extensionEditor.ts index 0eb852277ab..cbd45d0ebeb 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionEditor.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionEditor.ts @@ -855,12 +855,10 @@ export class ExtensionEditor extends EditorPane { extensionPackReadme.style.maxWidth = '882px'; const extensionPack = append(extensionPackReadme, $('div', { class: 'extension-pack' })); - if (manifest.extensionPack!.length <= 3) { + if (manifest.extensionPack!.length < 3) { extensionPackReadme.classList.add('one-row'); - } else if (manifest.extensionPack!.length <= 6) { + } else if (manifest.extensionPack!.length < 5) { extensionPackReadme.classList.add('two-rows'); - } else if (manifest.extensionPack!.length <= 9) { - extensionPackReadme.classList.add('three-rows'); } else { extensionPackReadme.classList.add('more-rows'); } diff --git a/src/vs/workbench/contrib/extensions/browser/media/extensionEditor.css b/src/vs/workbench/contrib/extensions/browser/media/extensionEditor.css index 174b332538b..575e6870b54 100644 --- a/src/vs/workbench/contrib/extensions/browser/media/extensionEditor.css +++ b/src/vs/workbench/contrib/extensions/browser/media/extensionEditor.css @@ -517,10 +517,6 @@ height: 224px; } -.extension-editor > .body > .content > .details > .readme-container > .extension-pack-readme.three-rows > .extension-pack { - height: 306px; -} - .extension-editor > .body > .content > .details > .readme-container > .extension-pack-readme.more-rows > .extension-pack { height: 326px; } From 0050133a605178b015565e3b02c2e418d2fe8e3b Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Thu, 24 Aug 2023 14:47:28 +0200 Subject: [PATCH 178/221] fix #189574 (#191209) --- .../common/abstractExtensionManagementService.ts | 2 +- .../contrib/extensions/browser/extensions.contribution.ts | 2 +- .../contrib/extensions/browser/extensionsWorkbenchService.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/platform/extensionManagement/common/abstractExtensionManagementService.ts b/src/vs/platform/extensionManagement/common/abstractExtensionManagementService.ts index 829a9b679c9..bcbc16146d7 100644 --- a/src/vs/platform/extensionManagement/common/abstractExtensionManagementService.ts +++ b/src/vs/platform/extensionManagement/common/abstractExtensionManagementService.ts @@ -154,7 +154,7 @@ export abstract class AbstractExtensionManagementService extends Disposable impl } async toggleAppliationScope(extension: ILocalExtension, fromProfileLocation: URI): Promise { - if (isApplicationScopedExtension(extension.manifest)) { + if (isApplicationScopedExtension(extension.manifest) || extension.isBuiltin) { return extension; } diff --git a/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts b/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts index 78f7de871fa..3d40bfa801d 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts @@ -1421,7 +1421,7 @@ class ExtensionsContributions extends Disposable implements IWorkbenchContributi menu: { id: MenuId.ExtensionContext, group: '2_configure', - when: ContextKeyExpr.and(ContextKeyExpr.equals('extensionStatus', 'installed'), ContextKeyExpr.has('isDefaultApplicationScopedExtension').negate()), + when: ContextKeyExpr.and(ContextKeyExpr.equals('extensionStatus', 'installed'), ContextKeyExpr.has('isDefaultApplicationScopedExtension').negate(), ContextKeyExpr.has('isBuiltinExtension').negate()), order: 3 }, run: async (accessor: ServicesAccessor, id: string) => { diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts b/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts index 96659a5f228..154696503e3 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts @@ -1622,7 +1622,7 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension } async toggleApplyExtensionToAllProfiles(extension: IExtension): Promise { - if (!extension.local || isApplicationScopedExtension(extension.local.manifest)) { + if (!extension.local || isApplicationScopedExtension(extension.local.manifest) || extension.isBuiltin) { return; } await this.extensionManagementService.toggleAppliationScope(extension.local, this.userDataProfileService.currentProfile.extensionsResource); From d0b353aa4d1d6c7ec62039628c22919b4f8ccfe9 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Thu, 24 Aug 2023 06:00:42 -0700 Subject: [PATCH 179/221] Add default values to EnvironmentVariableMutatorOptions --- src/vscode-dts/vscode.d.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/vscode-dts/vscode.d.ts b/src/vscode-dts/vscode.d.ts index 9904b311e50..d440e2d2fc1 100644 --- a/src/vscode-dts/vscode.d.ts +++ b/src/vscode-dts/vscode.d.ts @@ -11339,13 +11339,14 @@ declare module 'vscode' { */ export interface EnvironmentVariableMutatorOptions { /** - * Apply to the environment just before the process is created. + * Apply to the environment just before the process is created. Defaults to false. */ applyAtProcessCreation?: boolean; /** * Apply to the environment in the shell integration script. Note that this _will not_ apply - * the mutator if shell integration is disabled or not working for some reason. + * the mutator if shell integration is disabled or not working for some reason. Defaults to + * false. */ applyAtShellIntegration?: boolean; } From 1e822ef3f504b3940b26b1a1de1941ea06dafe48 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Thu, 24 Aug 2023 15:00:47 +0200 Subject: [PATCH 180/221] fix #190363 (#191210) --- .../browser/userDataProfileImportExportService.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/services/userDataProfile/browser/userDataProfileImportExportService.ts b/src/vs/workbench/services/userDataProfile/browser/userDataProfileImportExportService.ts index cea4e9de5f8..9dc107dd7fb 100644 --- a/src/vs/workbench/services/userDataProfile/browser/userDataProfileImportExportService.ts +++ b/src/vs/workbench/services/userDataProfile/browser/userDataProfileImportExportService.ts @@ -324,14 +324,15 @@ export class UserDataProfileImportExportService extends Disposable implements IU let result: { name: string; items: ReadonlyArray } | undefined; disposables.add(Event.any(quickPick.onDidCustom, quickPick.onDidAccept)(() => { - if (!quickPick.value) { - quickPick.validationMessage = localize('name required', "Provide a name for the new profile"); + const name = quickPick.value.trim(); + if (!name) { + quickPick.validationMessage = localize('name required', "Profile name is required and must be a non-empty value."); quickPick.severity = Severity.Error; } if (quickPick.validationMessage) { return; } - result = { name: quickPick.value, items: quickPick.selectedItems }; + result = { name, items: quickPick.selectedItems }; quickPick.hide(); quickPick.severity = Severity.Ignore; quickPick.validationMessage = undefined; From e64b9487bfa0aa84ae43aad57a0555a3cf20ef8f Mon Sep 17 00:00:00 2001 From: Henning Dieterichs Date: Thu, 24 Aug 2023 13:00:54 +0200 Subject: [PATCH 181/221] Fixes #189039 --- .../browser/widget/diffEditorWidget2/diffEditorEditors.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorEditors.ts b/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorEditors.ts index ee764c81aed..877f79ce430 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorEditors.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorEditors.ts @@ -50,6 +50,8 @@ export class DiffEditorEditors extends Disposable { /** @description update editor options */ _options.editorOptions.read(reader); + this._options.renderSideBySide.read(reader); + this.modified.updateOptions(this._adjustOptionsForRightHandSide(reader, changeSummary)); this.original.updateOptions(this._adjustOptionsForLeftHandSide(reader, changeSummary)); })); @@ -93,7 +95,11 @@ export class DiffEditorEditors extends Disposable { result.wordWrapOverride1 = 'off'; result.wordWrapOverride2 = 'off'; result.stickyScroll = { enabled: false }; + + // Disable unicode highlighting for the original side in inline mode, as they are not shown anyway. + result.unicodeHighlight = { nonBasicASCII: false, ambiguousCharacters: false, invisibleCharacters: false }; } else { + result.unicodeHighlight = this._options.editorOptions.get().unicodeHighlight; result.wordWrapOverride1 = this._options.diffWordWrap.get(); } if (changedOptions.originalAriaLabel) { From 1c3865f9ff21ce1aa46bee93f92d3e413d2e7b6d Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 24 Aug 2023 15:23:02 +0200 Subject: [PATCH 182/221] voice - make actions conditional --- .../node/voiceRecognitionService.ts | 8 +++++--- .../actions/chatVoiceInputActions.ts | 14 +++++++++----- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/vs/platform/voiceRecognition/node/voiceRecognitionService.ts b/src/vs/platform/voiceRecognition/node/voiceRecognitionService.ts index d2279001d75..fdcd3ac332d 100644 --- a/src/vs/platform/voiceRecognition/node/voiceRecognitionService.ts +++ b/src/vs/platform/voiceRecognition/node/voiceRecognitionService.ts @@ -6,6 +6,7 @@ import { CancellationToken } from 'vs/base/common/cancellation'; import { ILogService } from 'vs/platform/log/common/log'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; +import { IProductService } from 'vs/platform/product/common/productService'; export const IVoiceRecognitionService = createDecorator('voiceRecognitionService'); @@ -31,14 +32,15 @@ export class VoiceRecognitionService implements IVoiceRecognitionService { declare readonly _serviceBrand: undefined; constructor( - @ILogService private readonly logService: ILogService + @ILogService private readonly logService: ILogService, + @IProductService private readonly productService: IProductService ) { } async transcribe(channelData: Float32Array, cancellation: CancellationToken): Promise { this.logService.info(`[voice] transcribe(${channelData.length}): Begin`); - const modulePath = process.env.VSCODE_VOICE_MODULE_PATH; - if (!modulePath) { + const modulePath = process.env.VSCODE_VOICE_MODULE_PATH; // TODO@bpasero package + if (!modulePath || this.productService.quality === 'stable') { this.logService.error(`[voice] transcribe(${channelData.length}): Voice recognition not yet supported`); throw new Error('Voice recognition not yet supported!'); } diff --git a/src/vs/workbench/contrib/chat/electron-sandbox/actions/chatVoiceInputActions.ts b/src/vs/workbench/contrib/chat/electron-sandbox/actions/chatVoiceInputActions.ts index 91e0e6490c5..9ea3b0cde45 100644 --- a/src/vs/workbench/contrib/chat/electron-sandbox/actions/chatVoiceInputActions.ts +++ b/src/vs/workbench/contrib/chat/electron-sandbox/actions/chatVoiceInputActions.ts @@ -26,6 +26,8 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic import { getCodeEditor } from 'vs/editor/browser/editorBrowser'; import { isExecuteActionContext } from 'vs/workbench/contrib/chat/browser/actions/chatExecuteActions'; import { ICommandService } from 'vs/platform/commands/common/commands'; +import { process } from 'vs/base/parts/sandbox/electron-sandbox/globals'; +import product from 'vs/platform/product/common/product'; const CONTEXT_VOICE_CHAT_GETTING_READY = new RawContextKey('voiceChatGettingReady', false, { type: 'boolean', description: localize('voiceChatGettingReady', "True when there is voice input for chat getting ready.") }); const CONTEXT_VOICE_CHAT_IN_PROGRESS = new RawContextKey('voiceChatInProgress', false, { type: 'boolean', description: localize('voiceChatInProgress', "True when there is voice input for chat in progress.") }); @@ -374,10 +376,12 @@ class StopVoiceChatAction extends Action2 { } export function registerChatVoiceInputActions() { - registerAction2(VoiceChatInChatViewAction); - registerAction2(QuickVoiceChatAction); - registerAction2(InlineVoiceChatAction); + if (typeof process.env.VSCODE_VOICE_MODULE_PATH === 'string' && product.quality !== 'stable') { // TODO@bpasero package + registerAction2(VoiceChatInChatViewAction); + registerAction2(QuickVoiceChatAction); + registerAction2(InlineVoiceChatAction); - registerAction2(StartVoiceChatAction); - registerAction2(StopVoiceChatAction); + registerAction2(StartVoiceChatAction); + registerAction2(StopVoiceChatAction); + } } From 06f6caff51dafa6e9a855e4e747085047ecb8f4b Mon Sep 17 00:00:00 2001 From: Henning Dieterichs Date: Thu, 24 Aug 2023 11:03:02 +0200 Subject: [PATCH 183/221] Renames smart to legacy, standard to advanced --- src/vs/editor/browser/editorBrowser.ts | 2 +- src/vs/editor/browser/services/editorWorkerService.ts | 2 +- src/vs/editor/browser/widget/diffEditorWidget.ts | 2 +- .../widget/diffEditorWidget2/diffEditorViewModel.ts | 4 ++-- .../browser/widget/diffEditorWidget2/diffEditorWidget2.ts | 2 +- src/vs/editor/browser/widget/diffNavigator.ts | 2 +- src/vs/editor/browser/widget/diffReview.ts | 2 +- ...dLinesDiffComputer.ts => advancedLinesDiffComputer.ts} | 2 +- src/vs/editor/common/diff/algorithms/joinSequenceDiffs.ts | 2 +- ...artLinesDiffComputer.ts => legacyLinesDiffComputer.ts} | 2 +- src/vs/editor/common/diff/linesDiffComputers.ts | 8 ++++---- src/vs/editor/common/services/editorSimpleWorker.ts | 2 +- src/vs/editor/common/services/editorWorker.ts | 2 +- src/vs/editor/test/common/diff/diffComputer.test.ts | 2 +- .../test/common/services/testEditorWorkerService.ts | 2 +- src/vs/editor/test/node/diffing/diffingFixture.test.ts | 6 +++--- src/vs/editor/test/node/diffing/lineRangeMapping.test.ts | 2 +- src/vs/workbench/api/browser/mainThreadEditors.ts | 2 +- src/vs/workbench/api/common/extHost.protocol.ts | 2 +- .../workbench/contrib/notebook/common/notebookCommon.ts | 2 +- .../workbench/contrib/scm/browser/dirtydiffDecorator.ts | 2 +- 21 files changed, 27 insertions(+), 27 deletions(-) rename src/vs/editor/common/diff/{standardLinesDiffComputer.ts => advancedLinesDiffComputer.ts} (99%) rename src/vs/editor/common/diff/{smartLinesDiffComputer.ts => legacyLinesDiffComputer.ts} (99%) diff --git a/src/vs/editor/browser/editorBrowser.ts b/src/vs/editor/browser/editorBrowser.ts index ae6cfd542d3..1ea2dff1bb6 100644 --- a/src/vs/editor/browser/editorBrowser.ts +++ b/src/vs/editor/browser/editorBrowser.ts @@ -15,7 +15,7 @@ import { IRange, Range } from 'vs/editor/common/core/range'; import { Selection } from 'vs/editor/common/core/selection'; import { IWordAtPosition } from 'vs/editor/common/core/wordHelper'; import { ICursorPositionChangedEvent, ICursorSelectionChangedEvent } from 'vs/editor/common/cursorEvents'; -import { IDiffComputationResult, ILineChange } from 'vs/editor/common/diff/smartLinesDiffComputer'; +import { IDiffComputationResult, ILineChange } from 'vs/editor/common/diff/legacyLinesDiffComputer'; import * as editorCommon from 'vs/editor/common/editorCommon'; import { GlyphMarginLane, ICursorStateComputer, IIdentifiedSingleEditOperation, IModelDecoration, IModelDeltaDecoration, ITextModel, PositionAffinity } from 'vs/editor/common/model'; import { InjectedText } from 'vs/editor/common/modelLineProjectionData'; diff --git a/src/vs/editor/browser/services/editorWorkerService.ts b/src/vs/editor/browser/services/editorWorkerService.ts index 6757066169f..993fe8e813c 100644 --- a/src/vs/editor/browser/services/editorWorkerService.ts +++ b/src/vs/editor/browser/services/editorWorkerService.ts @@ -24,7 +24,7 @@ import { canceled, onUnexpectedError } from 'vs/base/common/errors'; import { UnicodeHighlighterOptions } from 'vs/editor/common/services/unicodeTextModelHighlighter'; import { IEditorWorkerHost } from 'vs/editor/common/services/editorWorkerHost'; import { ILanguageFeaturesService } from 'vs/editor/common/services/languageFeatures'; -import { IChange } from 'vs/editor/common/diff/smartLinesDiffComputer'; +import { IChange } from 'vs/editor/common/diff/legacyLinesDiffComputer'; import { IDocumentDiff, IDocumentDiffProviderOptions } from 'vs/editor/common/diff/documentDiffProvider'; import { ILinesDiffComputerOptions, LineRangeMapping, MovedText, RangeMapping, SimpleLineRangeMapping } from 'vs/editor/common/diff/linesDiffComputer'; import { LineRange } from 'vs/editor/common/core/lineRange'; diff --git a/src/vs/editor/browser/widget/diffEditorWidget.ts b/src/vs/editor/browser/widget/diffEditorWidget.ts index 4eae29a335e..e1a43acbaf6 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget.ts @@ -40,7 +40,7 @@ import { IPosition, Position } from 'vs/editor/common/core/position'; import { IRange, Range } from 'vs/editor/common/core/range'; import { ISelection, Selection } from 'vs/editor/common/core/selection'; import { StringBuilder } from 'vs/editor/common/core/stringBuilder'; -import { IChange, ICharChange, IDiffComputationResult, ILineChange } from 'vs/editor/common/diff/smartLinesDiffComputer'; +import { IChange, ICharChange, IDiffComputationResult, ILineChange } from 'vs/editor/common/diff/legacyLinesDiffComputer'; import * as editorCommon from 'vs/editor/common/editorCommon'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; import { IModelDecorationsChangeAccessor, IModelDeltaDecoration, ITextModel } from 'vs/editor/common/model'; diff --git a/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorViewModel.ts b/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorViewModel.ts index 8dea4d6cc56..7927623f49b 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorViewModel.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorViewModel.ts @@ -11,7 +11,7 @@ import { ISerializedLineRange, LineRange } from 'vs/editor/common/core/lineRange import { Range } from 'vs/editor/common/core/range'; import { IDocumentDiff, IDocumentDiffProvider } from 'vs/editor/common/diff/documentDiffProvider'; import { LineRangeMapping, MovedText, RangeMapping, SimpleLineRangeMapping } from 'vs/editor/common/diff/linesDiffComputer'; -import { StandardLinesDiffComputer, lineRangeMappingFromRangeMappings } from 'vs/editor/common/diff/standardLinesDiffComputer'; +import { AdvancedLinesDiffComputer, lineRangeMappingFromRangeMappings } from 'vs/editor/common/diff/advancedLinesDiffComputer'; import { IDiffEditorModel, IDiffEditorViewModel } from 'vs/editor/common/editorCommon'; import { ITextModel } from 'vs/editor/common/model'; import { TextEditInfo } from 'vs/editor/common/model/bracketPairsTextModelPart/bracketPairsTree/beforeEditPositionMapper'; @@ -162,7 +162,7 @@ export class DiffEditorViewModel extends Disposable implements IDiffEditorViewMo debouncer.cancel(); contentChangedSignal.read(reader); documentDiffProviderOptionChanged.read(reader); - readHotReloadableExport(StandardLinesDiffComputer, reader); + readHotReloadableExport(AdvancedLinesDiffComputer, reader); this._isDiffUpToDate.set(false, undefined); diff --git a/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2.ts b/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2.ts index 5bc2b098e2b..280c2bb7b9a 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2.ts @@ -30,7 +30,7 @@ import { Position } from 'vs/editor/common/core/position'; import { Range } from 'vs/editor/common/core/range'; import { CursorChangeReason } from 'vs/editor/common/cursorEvents'; import { LineRangeMapping } from 'vs/editor/common/diff/linesDiffComputer'; -import { IDiffComputationResult, ILineChange } from 'vs/editor/common/diff/smartLinesDiffComputer'; +import { IDiffComputationResult, ILineChange } from 'vs/editor/common/diff/legacyLinesDiffComputer'; import { EditorType, IDiffEditorModel, IDiffEditorViewModel, IDiffEditorViewState } from 'vs/editor/common/editorCommon'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; import { IIdentifiedSingleEditOperation } from 'vs/editor/common/model'; diff --git a/src/vs/editor/browser/widget/diffNavigator.ts b/src/vs/editor/browser/widget/diffNavigator.ts index 0f34a1e5960..1edce99edf6 100644 --- a/src/vs/editor/browser/widget/diffNavigator.ts +++ b/src/vs/editor/browser/widget/diffNavigator.ts @@ -10,7 +10,7 @@ import * as objects from 'vs/base/common/objects'; import { IDiffEditor } from 'vs/editor/browser/editorBrowser'; import { ICursorPositionChangedEvent } from 'vs/editor/common/cursorEvents'; import { Range } from 'vs/editor/common/core/range'; -import { ILineChange } from 'vs/editor/common/diff/smartLinesDiffComputer'; +import { ILineChange } from 'vs/editor/common/diff/legacyLinesDiffComputer'; import { ScrollType } from 'vs/editor/common/editorCommon'; import { AudioCue, IAudioCueService } from 'vs/platform/audioCues/browser/audioCueService'; import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService'; diff --git a/src/vs/editor/browser/widget/diffReview.ts b/src/vs/editor/browser/widget/diffReview.ts index ea813d85aa5..268d41d2f3b 100644 --- a/src/vs/editor/browser/widget/diffReview.ts +++ b/src/vs/editor/browser/widget/diffReview.ts @@ -19,7 +19,7 @@ import { applyFontInfo } from 'vs/editor/browser/config/domFontInfo'; import { DiffEditorWidget } from 'vs/editor/browser/widget/diffEditorWidget'; import { EditorFontLigatures, EditorOption, IComputedEditorOptions } from 'vs/editor/common/config/editorOptions'; import { Position } from 'vs/editor/common/core/position'; -import { ILineChange } from 'vs/editor/common/diff/smartLinesDiffComputer'; +import { ILineChange } from 'vs/editor/common/diff/legacyLinesDiffComputer'; import { ScrollType } from 'vs/editor/common/editorCommon'; import { ILanguageIdCodec } from 'vs/editor/common/languages'; import { ILanguageService } from 'vs/editor/common/languages/language'; diff --git a/src/vs/editor/common/diff/standardLinesDiffComputer.ts b/src/vs/editor/common/diff/advancedLinesDiffComputer.ts similarity index 99% rename from src/vs/editor/common/diff/standardLinesDiffComputer.ts rename to src/vs/editor/common/diff/advancedLinesDiffComputer.ts index 20279a9fe68..61fd21d9c29 100644 --- a/src/vs/editor/common/diff/standardLinesDiffComputer.ts +++ b/src/vs/editor/common/diff/advancedLinesDiffComputer.ts @@ -17,7 +17,7 @@ import { optimizeSequenceDiffs, removeRandomLineMatches, removeRandomMatches, sm import { MyersDiffAlgorithm } from 'vs/editor/common/diff/algorithms/myersDiffAlgorithm'; import { ILinesDiffComputer, ILinesDiffComputerOptions, LineRangeMapping, LinesDiff, MovedText, RangeMapping, SimpleLineRangeMapping } from 'vs/editor/common/diff/linesDiffComputer'; -export class StandardLinesDiffComputer implements ILinesDiffComputer { +export class AdvancedLinesDiffComputer implements ILinesDiffComputer { private readonly dynamicProgrammingDiffing = new DynamicProgrammingDiffing(); private readonly myersDiffingAlgorithm = new MyersDiffAlgorithm(); diff --git a/src/vs/editor/common/diff/algorithms/joinSequenceDiffs.ts b/src/vs/editor/common/diff/algorithms/joinSequenceDiffs.ts index c79d557e409..cef14d466c8 100644 --- a/src/vs/editor/common/diff/algorithms/joinSequenceDiffs.ts +++ b/src/vs/editor/common/diff/algorithms/joinSequenceDiffs.ts @@ -5,7 +5,7 @@ import { OffsetRange } from 'vs/editor/common/core/offsetRange'; import { ISequence, SequenceDiff } from 'vs/editor/common/diff/algorithms/diffAlgorithm'; -import { LineSequence, LinesSliceCharSequence } from 'vs/editor/common/diff/standardLinesDiffComputer'; +import { LineSequence, LinesSliceCharSequence } from 'vs/editor/common/diff/advancedLinesDiffComputer'; export function optimizeSequenceDiffs(sequence1: ISequence, sequence2: ISequence, sequenceDiffs: SequenceDiff[]): SequenceDiff[] { let result = sequenceDiffs; diff --git a/src/vs/editor/common/diff/smartLinesDiffComputer.ts b/src/vs/editor/common/diff/legacyLinesDiffComputer.ts similarity index 99% rename from src/vs/editor/common/diff/smartLinesDiffComputer.ts rename to src/vs/editor/common/diff/legacyLinesDiffComputer.ts index fe7fdcdc5bf..5ea6524a41e 100644 --- a/src/vs/editor/common/diff/smartLinesDiffComputer.ts +++ b/src/vs/editor/common/diff/legacyLinesDiffComputer.ts @@ -13,7 +13,7 @@ import { LineRange } from 'vs/editor/common/core/lineRange'; const MINIMUM_MATCHING_CHARACTER_LENGTH = 3; -export class SmartLinesDiffComputer implements ILinesDiffComputer { +export class LegacyLinesDiffComputer implements ILinesDiffComputer { computeDiff(originalLines: string[], modifiedLines: string[], options: ILinesDiffComputerOptions): LinesDiff { const diffComputer = new DiffComputer(originalLines, modifiedLines, { maxComputationTime: options.maxComputationTimeMs, diff --git a/src/vs/editor/common/diff/linesDiffComputers.ts b/src/vs/editor/common/diff/linesDiffComputers.ts index 415c72e8f04..727b91455b7 100644 --- a/src/vs/editor/common/diff/linesDiffComputers.ts +++ b/src/vs/editor/common/diff/linesDiffComputers.ts @@ -3,10 +3,10 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { SmartLinesDiffComputer } from 'vs/editor/common/diff/smartLinesDiffComputer'; -import { StandardLinesDiffComputer } from 'vs/editor/common/diff/standardLinesDiffComputer'; +import { LegacyLinesDiffComputer } from 'vs/editor/common/diff/legacyLinesDiffComputer'; +import { AdvancedLinesDiffComputer } from 'vs/editor/common/diff/advancedLinesDiffComputer'; export const linesDiffComputers = { - getLegacy: () => new SmartLinesDiffComputer(), - getAdvanced: () => new StandardLinesDiffComputer(), + getLegacy: () => new LegacyLinesDiffComputer(), + getAdvanced: () => new AdvancedLinesDiffComputer(), }; diff --git a/src/vs/editor/common/services/editorSimpleWorker.ts b/src/vs/editor/common/services/editorSimpleWorker.ts index 2c26721fd47..ca8364f62d3 100644 --- a/src/vs/editor/common/services/editorSimpleWorker.ts +++ b/src/vs/editor/common/services/editorSimpleWorker.ts @@ -20,7 +20,7 @@ import { createMonacoBaseAPI } from 'vs/editor/common/services/editorBaseApi'; import { IEditorWorkerHost } from 'vs/editor/common/services/editorWorkerHost'; import { StopWatch } from 'vs/base/common/stopwatch'; import { UnicodeTextModelHighlighter, UnicodeHighlighterOptions } from 'vs/editor/common/services/unicodeTextModelHighlighter'; -import { DiffComputer, IChange } from 'vs/editor/common/diff/smartLinesDiffComputer'; +import { DiffComputer, IChange } from 'vs/editor/common/diff/legacyLinesDiffComputer'; import { ILinesDiffComputer, ILinesDiffComputerOptions, LineRangeMapping } from 'vs/editor/common/diff/linesDiffComputer'; import { linesDiffComputers } from 'vs/editor/common/diff/linesDiffComputers'; import { createProxyObject, getAllMethodNames } from 'vs/base/common/objects'; diff --git a/src/vs/editor/common/services/editorWorker.ts b/src/vs/editor/common/services/editorWorker.ts index 9038e313a9c..9e1cca8a460 100644 --- a/src/vs/editor/common/services/editorWorker.ts +++ b/src/vs/editor/common/services/editorWorker.ts @@ -6,7 +6,7 @@ import { URI } from 'vs/base/common/uri'; import { IRange } from 'vs/editor/common/core/range'; import { IDocumentDiff, IDocumentDiffProviderOptions } from 'vs/editor/common/diff/documentDiffProvider'; -import { IChange } from 'vs/editor/common/diff/smartLinesDiffComputer'; +import { IChange } from 'vs/editor/common/diff/legacyLinesDiffComputer'; import { IInplaceReplaceSupportResult, TextEdit } from 'vs/editor/common/languages'; import { UnicodeHighlighterOptions } from 'vs/editor/common/services/unicodeTextModelHighlighter'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; diff --git a/src/vs/editor/test/common/diff/diffComputer.test.ts b/src/vs/editor/test/common/diff/diffComputer.test.ts index a8eb52b07c1..aca599dc6e5 100644 --- a/src/vs/editor/test/common/diff/diffComputer.test.ts +++ b/src/vs/editor/test/common/diff/diffComputer.test.ts @@ -5,7 +5,7 @@ import * as assert from 'assert'; import { Constants } from 'vs/base/common/uint'; import { Range } from 'vs/editor/common/core/range'; -import { DiffComputer, ICharChange, ILineChange } from 'vs/editor/common/diff/smartLinesDiffComputer'; +import { DiffComputer, ICharChange, ILineChange } from 'vs/editor/common/diff/legacyLinesDiffComputer'; import { IIdentifiedSingleEditOperation, ITextModel } from 'vs/editor/common/model'; import { createTextModel } from 'vs/editor/test/common/testTextModel'; diff --git a/src/vs/editor/test/common/services/testEditorWorkerService.ts b/src/vs/editor/test/common/services/testEditorWorkerService.ts index 640a3e4b596..e6693d821e9 100644 --- a/src/vs/editor/test/common/services/testEditorWorkerService.ts +++ b/src/vs/editor/test/common/services/testEditorWorkerService.ts @@ -8,7 +8,7 @@ import { IRange } from 'vs/editor/common/core/range'; import { DiffAlgorithmName, IEditorWorkerService, IUnicodeHighlightsResult } from 'vs/editor/common/services/editorWorker'; import { TextEdit, IInplaceReplaceSupportResult } from 'vs/editor/common/languages'; import { IDocumentDiff, IDocumentDiffProviderOptions } from 'vs/editor/common/diff/documentDiffProvider'; -import { IChange } from 'vs/editor/common/diff/smartLinesDiffComputer'; +import { IChange } from 'vs/editor/common/diff/legacyLinesDiffComputer'; export class TestEditorWorkerService implements IEditorWorkerService { diff --git a/src/vs/editor/test/node/diffing/diffingFixture.test.ts b/src/vs/editor/test/node/diffing/diffingFixture.test.ts index 59173290fc8..a04f2edf9d8 100644 --- a/src/vs/editor/test/node/diffing/diffingFixture.test.ts +++ b/src/vs/editor/test/node/diffing/diffingFixture.test.ts @@ -9,8 +9,8 @@ import { join, resolve } from 'path'; import { setUnexpectedErrorHandler } from 'vs/base/common/errors'; import { FileAccess } from 'vs/base/common/network'; import { LineRangeMapping } from 'vs/editor/common/diff/linesDiffComputer'; -import { SmartLinesDiffComputer } from 'vs/editor/common/diff/smartLinesDiffComputer'; -import { StandardLinesDiffComputer } from 'vs/editor/common/diff/standardLinesDiffComputer'; +import { LegacyLinesDiffComputer } from 'vs/editor/common/diff/legacyLinesDiffComputer'; +import { AdvancedLinesDiffComputer } from 'vs/editor/common/diff/advancedLinesDiffComputer'; suite('diff fixtures', () => { setup(() => { @@ -38,7 +38,7 @@ suite('diff fixtures', () => { const secondContent = readFileSync(join(folderPath, secondFileName), 'utf8').replaceAll('\r\n', '\n').replaceAll('\r', '\n'); const secondContentLines = secondContent.split(/\n/); - const diffingAlgo = diffingAlgoName === 'legacy' ? new SmartLinesDiffComputer() : new StandardLinesDiffComputer(); + const diffingAlgo = diffingAlgoName === 'legacy' ? new LegacyLinesDiffComputer() : new AdvancedLinesDiffComputer(); const ignoreTrimWhitespace = folder.indexOf('trimws') >= 0; const diff = diffingAlgo.computeDiff(firstContentLines, secondContentLines, { ignoreTrimWhitespace, maxComputationTimeMs: Number.MAX_SAFE_INTEGER, computeMoves: false }); diff --git a/src/vs/editor/test/node/diffing/lineRangeMapping.test.ts b/src/vs/editor/test/node/diffing/lineRangeMapping.test.ts index 5cda2c94794..f0d0802912d 100644 --- a/src/vs/editor/test/node/diffing/lineRangeMapping.test.ts +++ b/src/vs/editor/test/node/diffing/lineRangeMapping.test.ts @@ -6,7 +6,7 @@ import * as assert from 'assert'; import { Range } from 'vs/editor/common/core/range'; import { RangeMapping } from 'vs/editor/common/diff/linesDiffComputer'; -import { getLineRangeMapping } from 'vs/editor/common/diff/standardLinesDiffComputer'; +import { getLineRangeMapping } from 'vs/editor/common/diff/advancedLinesDiffComputer'; suite('lineRangeMapping', () => { test('1', () => { diff --git a/src/vs/workbench/api/browser/mainThreadEditors.ts b/src/vs/workbench/api/browser/mainThreadEditors.ts index 552241c27d7..b5e8bb0ef56 100644 --- a/src/vs/workbench/api/browser/mainThreadEditors.ts +++ b/src/vs/workbench/api/browser/mainThreadEditors.ts @@ -23,7 +23,7 @@ import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editor import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IWorkingCopyService } from 'vs/workbench/services/workingCopy/common/workingCopyService'; import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; -import { IChange } from 'vs/editor/common/diff/smartLinesDiffComputer'; +import { IChange } from 'vs/editor/common/diff/legacyLinesDiffComputer'; import { IExtHostContext } from 'vs/workbench/services/extensions/common/extHostCustomers'; import { IEditorControl } from 'vs/workbench/common/editor'; import { getCodeEditor, ICodeEditor } from 'vs/editor/browser/editorBrowser'; diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index e4964fb5670..82646f45cac 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -19,7 +19,7 @@ import { ISingleEditOperation } from 'vs/editor/common/core/editOperation'; import { IPosition } from 'vs/editor/common/core/position'; import { IRange } from 'vs/editor/common/core/range'; import { ISelection, Selection } from 'vs/editor/common/core/selection'; -import { IChange } from 'vs/editor/common/diff/smartLinesDiffComputer'; +import { IChange } from 'vs/editor/common/diff/legacyLinesDiffComputer'; import * as editorCommon from 'vs/editor/common/editorCommon'; import { StandardTokenType } from 'vs/editor/common/encodedTokenAttributes'; import * as languages from 'vs/editor/common/languages'; diff --git a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts index e01a5c37361..90a0451aae1 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts @@ -15,7 +15,7 @@ import { basename } from 'vs/base/common/path'; import { isWindows } from 'vs/base/common/platform'; import { ISplice } from 'vs/base/common/sequence'; import { URI, UriComponents } from 'vs/base/common/uri'; -import { ILineChange } from 'vs/editor/common/diff/smartLinesDiffComputer'; +import { ILineChange } from 'vs/editor/common/diff/legacyLinesDiffComputer'; import * as editorCommon from 'vs/editor/common/editorCommon'; import { Command, WorkspaceEditMetadata } from 'vs/editor/common/languages'; import { IReadonlyTextBuffer } from 'vs/editor/common/model'; diff --git a/src/vs/workbench/contrib/scm/browser/dirtydiffDecorator.ts b/src/vs/workbench/contrib/scm/browser/dirtydiffDecorator.ts index 41ac8d05a2b..589c0e5e99d 100644 --- a/src/vs/workbench/contrib/scm/browser/dirtydiffDecorator.ts +++ b/src/vs/workbench/contrib/scm/browser/dirtydiffDecorator.ts @@ -50,7 +50,7 @@ import { ThemeIcon } from 'vs/base/common/themables'; import { onUnexpectedError } from 'vs/base/common/errors'; import { TextCompareEditorActiveContext } from 'vs/workbench/common/contextkeys'; import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/progress'; -import { IChange } from 'vs/editor/common/diff/smartLinesDiffComputer'; +import { IChange } from 'vs/editor/common/diff/legacyLinesDiffComputer'; import { Color } from 'vs/base/common/color'; import { ResourceMap } from 'vs/base/common/map'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; From 905931a8683a6e4e51e15ce4f116aae976752eb7 Mon Sep 17 00:00:00 2001 From: Henning Dieterichs Date: Thu, 24 Aug 2023 11:29:53 +0200 Subject: [PATCH 184/221] Fixes CI --- build/monaco/monaco.d.ts.recipe | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/monaco/monaco.d.ts.recipe b/build/monaco/monaco.d.ts.recipe index ff4febe8ce6..89c884f18a0 100644 --- a/build/monaco/monaco.d.ts.recipe +++ b/build/monaco/monaco.d.ts.recipe @@ -107,7 +107,7 @@ export interface ICommandHandler { #include(vs/editor/common/core/editOperation): ISingleEditOperation #include(vs/editor/common/core/wordHelper): IWordAtPosition #includeAll(vs/editor/common/model): IScrollEvent -#include(vs/editor/common/diff/smartLinesDiffComputer): IChange, ICharChange, ILineChange +#include(vs/editor/common/diff/legacyLinesDiffComputer): IChange, ICharChange, ILineChange #include(vs/editor/common/diff/documentDiffProvider): IDocumentDiffProvider, IDocumentDiffProviderOptions, IDocumentDiff #include(vs/editor/common/core/lineRange): LineRange #include(vs/editor/common/diff/linesDiffComputer): LineRangeMapping, RangeMapping, MovedText, SimpleLineRangeMapping From 1f9f663d1d0329e8e8b6e79bc73d3f237e5a87b8 Mon Sep 17 00:00:00 2001 From: Henning Dieterichs Date: Thu, 24 Aug 2023 13:13:28 +0200 Subject: [PATCH 185/221] Fixes #189327 --- .../diffEditorWidget2/diffEditorViewModel.ts | 13 +++++++++++-- .../widget/workerBasedDocumentDiffProvider.ts | 15 +++++++++++++-- src/vs/editor/common/diff/documentDiffProvider.ts | 3 ++- src/vs/monaco.d.ts | 2 +- 4 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorViewModel.ts b/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorViewModel.ts index 7927623f49b..a41ba6a9909 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorViewModel.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorViewModel.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { RunOnceScheduler } from 'vs/base/common/async'; -import { Disposable } from 'vs/base/common/lifecycle'; +import { Disposable, toDisposable } from 'vs/base/common/lifecycle'; import { IObservable, IReader, ISettableObservable, ITransaction, autorunWithStore, derived, observableSignal, observableSignalFromEvent, observableValue, transaction, waitForState } from 'vs/base/common/observable'; import { isDefined } from 'vs/base/common/types'; import { ISerializedLineRange, LineRange } from 'vs/editor/common/core/lineRange'; @@ -19,6 +19,7 @@ import { combineTextEditInfos } from 'vs/editor/common/model/bracketPairsTextMod import { lengthAdd, lengthDiffNonNegative, lengthGetLineCount, lengthOfRange, lengthToPosition, lengthZero, positionToLength } from 'vs/editor/common/model/bracketPairsTextModelPart/bracketPairsTree/length'; import { DiffEditorOptions } from './diffEditorOptions'; import { readHotReloadableExport } from 'vs/editor/browser/widget/diffEditorWidget2/utils'; +import { CancellationTokenSource } from 'vs/base/common/cancellation'; export class DiffEditorViewModel extends Disposable implements IDiffEditorViewModel { private readonly _isDiffUpToDate = observableValue('isDiffUpToDate', false); @@ -64,6 +65,8 @@ export class DiffEditorViewModel extends Disposable implements IDiffEditorViewMo this._hoveredMovedText.set(movedText, undefined); } + private readonly _cancellationTokenSource = new CancellationTokenSource(); + constructor( public readonly model: IDiffEditorModel, private readonly _options: DiffEditorOptions, @@ -71,6 +74,8 @@ export class DiffEditorViewModel extends Disposable implements IDiffEditorViewMo ) { super(); + this._register(toDisposable(() => this._cancellationTokenSource.cancel())); + const contentChangedSignal = observableSignal('contentChangedSignal'); const debouncer = this._register(new RunOnceScheduler(() => contentChangedSignal.trigger(undefined), 200)); @@ -182,7 +187,11 @@ export class DiffEditorViewModel extends Disposable implements IDiffEditorViewMo ignoreTrimWhitespace: this._options.ignoreTrimWhitespace.read(reader), maxComputationTimeMs: this._options.maxComputationTimeMs.read(reader), computeMoves: this._options.showMoves.read(reader), - }); + }, this._cancellationTokenSource.token); + + if (this._cancellationTokenSource.token.isCancellationRequested) { + return; + } result = applyOriginalEdits(result, originalTextEditInfos, model.original, model.modified) ?? result; result = applyModifiedEdits(result, modifiedTextEditInfos, model.original, model.modified) ?? result; diff --git a/src/vs/editor/browser/widget/workerBasedDocumentDiffProvider.ts b/src/vs/editor/browser/widget/workerBasedDocumentDiffProvider.ts index cca1f5ab297..648ba44763c 100644 --- a/src/vs/editor/browser/widget/workerBasedDocumentDiffProvider.ts +++ b/src/vs/editor/browser/widget/workerBasedDocumentDiffProvider.ts @@ -3,6 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { CancellationToken } from 'vs/base/common/cancellation'; import { Emitter, Event } from 'vs/base/common/event'; import { IDisposable } from 'vs/base/common/lifecycle'; import { StopWatch } from 'vs/base/common/stopwatch'; @@ -34,9 +35,9 @@ export class WorkerBasedDocumentDiffProvider implements IDocumentDiffProvider, I this.diffAlgorithmOnDidChangeSubscription?.dispose(); } - async computeDiff(original: ITextModel, modified: ITextModel, options: IDocumentDiffProviderOptions): Promise { + async computeDiff(original: ITextModel, modified: ITextModel, options: IDocumentDiffProviderOptions, cancellationToken: CancellationToken): Promise { if (typeof this.diffAlgorithm !== 'string') { - return this.diffAlgorithm.computeDiff(original, modified, options); + return this.diffAlgorithm.computeDiff(original, modified, options, cancellationToken); } // This significantly speeds up the case when the original file is empty @@ -95,6 +96,16 @@ export class WorkerBasedDocumentDiffProvider implements IDocumentDiffProvider, I timedOut: result?.quitEarly ?? true, }); + if (cancellationToken.isCancellationRequested) { + // Text models might be disposed! + return { + changes: [], + identical: false, + quitEarly: true, + moves: [], + }; + } + if (!result) { throw new Error('no diff result available'); } diff --git a/src/vs/editor/common/diff/documentDiffProvider.ts b/src/vs/editor/common/diff/documentDiffProvider.ts index ad707d114b5..02907dddca3 100644 --- a/src/vs/editor/common/diff/documentDiffProvider.ts +++ b/src/vs/editor/common/diff/documentDiffProvider.ts @@ -3,6 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { CancellationToken } from 'vs/base/common/cancellation'; import { Event } from 'vs/base/common/event'; import { LineRangeMapping, MovedText } from 'vs/editor/common/diff/linesDiffComputer'; import { ITextModel } from 'vs/editor/common/model'; @@ -14,7 +15,7 @@ export interface IDocumentDiffProvider { /** * Computes the diff between the text models `original` and `modified`. */ - computeDiff(original: ITextModel, modified: ITextModel, options: IDocumentDiffProviderOptions): Promise; + computeDiff(original: ITextModel, modified: ITextModel, options: IDocumentDiffProviderOptions, cancellationToken: CancellationToken): Promise; /** * Is fired when settings of the diff algorithm change that could alter the result of the diffing computation. diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index 544197938c2..2d030c3fa23 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -2374,7 +2374,7 @@ declare namespace monaco.editor { /** * Computes the diff between the text models `original` and `modified`. */ - computeDiff(original: ITextModel, modified: ITextModel, options: IDocumentDiffProviderOptions): Promise; + computeDiff(original: ITextModel, modified: ITextModel, options: IDocumentDiffProviderOptions, cancellationToken: CancellationToken): Promise; /** * Is fired when settings of the diff algorithm change that could alter the result of the diffing computation. * Any user of this provider should recompute the diff when this event is fired. From 4d9f1fc9c92bde758245ed28aa3a8389d5f4d745 Mon Sep 17 00:00:00 2001 From: Henning Dieterichs Date: Thu, 24 Aug 2023 14:37:09 +0200 Subject: [PATCH 186/221] Fixes CI --- src/vs/editor/browser/widget/diffEditorWidget.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vs/editor/browser/widget/diffEditorWidget.ts b/src/vs/editor/browser/widget/diffEditorWidget.ts index e1a43acbaf6..5588ae6f5ec 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget.ts @@ -11,6 +11,7 @@ import { MOUSE_CURSOR_TEXT_CSS_CLASS_NAME } from 'vs/base/browser/ui/mouseCursor import { IBoundarySashes, ISashEvent, IVerticalSashLayoutProvider, Orientation, Sash, SashState } from 'vs/base/browser/ui/sash/sash'; import * as assert from 'vs/base/common/assert'; import { RunOnceScheduler } from 'vs/base/common/async'; +import { CancellationToken } from 'vs/base/common/cancellation'; import { Codicon } from 'vs/base/common/codicons'; import { Color } from 'vs/base/common/color'; import { onUnexpectedError } from 'vs/base/common/errors'; @@ -1186,7 +1187,7 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE ignoreTrimWhitespace: this._options.ignoreTrimWhitespace, maxComputationTimeMs: this._options.maxComputationTime, computeMoves: false, - }).then(result => { + }, CancellationToken.None).then(result => { if (currentToken === this._diffComputationToken && currentOriginalModel === this._originalEditor.getModel() && currentModifiedModel === this._modifiedEditor.getModel() From 94ad4e5e1fb341c48ebda57b786e5785f0338e85 Mon Sep 17 00:00:00 2001 From: meganrogge Date: Thu, 24 Aug 2023 08:13:35 -0700 Subject: [PATCH 187/221] address feedback --- .../terminal.accessibility.contribution.ts | 10 +---- .../browser/terminalAccessibleWidget.ts | 40 +++++++++---------- 2 files changed, 21 insertions(+), 29 deletions(-) diff --git a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminal.accessibility.contribution.ts b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminal.accessibility.contribution.ts index 4eb13c439a6..96b9602e45d 100644 --- a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminal.accessibility.contribution.ts +++ b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminal.accessibility.contribution.ts @@ -48,7 +48,7 @@ class TextAreaSyncContribution extends DisposableStore implements ITerminalContr } registerTerminalContribution(TextAreaSyncContribution.ID, TextAreaSyncContribution); -export class AccessibleBufferContribution extends DisposableStore implements ITerminalContribution { +class AccessibleBufferContribution extends DisposableStore implements ITerminalContribution { static readonly ID = 'terminal.accessible-buffer'; private _xterm: IXtermTerminal & { raw: Terminal } | undefined; static get(instance: ITerminalInstance): AccessibleBufferContribution | null { @@ -220,13 +220,7 @@ registerTerminalAction({ precondition: ContextKeyExpr.or(TerminalContextKeys.processSupported, TerminalContextKeys.terminalHasBeenCreated), run: async (c) => { const instance = c.service.activeInstance || await c.service.createTerminal({ location: TerminalLocation.Panel }); - if (!instance) { - return; - } - const contribution = instance.getContribution('terminal.accessible-buffer'); - if (contribution) { - contribution.hide(); - } + instance.getContribution(AccessibleBufferContribution.ID)?.hide(); instance.focus(true); } }); diff --git a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleWidget.ts b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleWidget.ts index 77fd6173934..f25793c1da9 100644 --- a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleWidget.ts +++ b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleWidget.ts @@ -40,16 +40,16 @@ export abstract class TerminalAccessibleWidget extends DisposableStore { protected _listeners: IDisposable[] = []; - private readonly _focusedContextKey?: IContextKey; - private readonly _focusedLastLineContextKey?: IContextKey; + private readonly _focusedContextKey: IContextKey; + private readonly _focusedLastLineContextKey: IContextKey; private readonly _focusTracker?: dom.IFocusTracker; constructor( private readonly _className: string, protected readonly _instance: Pick, protected readonly _xterm: Pick & { raw: Terminal }, - private _focusContextKey: RawContextKey | undefined, - private _focusLastLineContextKey: RawContextKey | undefined, + private rawFocusContextKey: RawContextKey, + private rawFocusLastLineContextKey: RawContextKey, @IInstantiationService private readonly _instantiationService: IInstantiationService, @IModelService private readonly _modelService: IModelService, @IConfigurationService private readonly _configurationService: IConfigurationService, @@ -89,23 +89,21 @@ export abstract class TerminalAccessibleWidget extends DisposableStore { this._element.replaceChildren(this._editorContainer); this._xtermElement.insertAdjacentElement('beforebegin', this._element); - if (this._focusContextKey && this._focusLastLineContextKey) { - this._focusTracker = this.add(dom.trackFocus(this._editorContainer)); - this._focusedContextKey = this._focusContextKey.bindTo(this._contextKeyService); - this._focusedLastLineContextKey = this._focusLastLineContextKey.bindTo(this._contextKeyService); - this.add(this._focusTracker.onDidFocus(() => { - this._focusedContextKey?.set(true); - this._focusedLastLineContextKey?.set(this._editorWidget.getSelection()?.positionLineNumber === this._editorWidget.getModel()?.getLineCount()); - })); - this.add(this._focusTracker.onDidBlur(() => { - this._focusedContextKey?.reset(); - this._focusedLastLineContextKey?.reset(); - })); - this._editorWidget.onDidChangeCursorPosition(() => { - console.log(this._editorWidget.getSelection()?.positionLineNumber === this._editorWidget.getModel()?.getLineCount()); - this._focusedLastLineContextKey?.set(this._editorWidget.getSelection()?.positionLineNumber === this._editorWidget.getModel()?.getLineCount()); - }); - } + this._focusTracker = this.add(dom.trackFocus(this._editorContainer)); + this._focusedContextKey = this.rawFocusContextKey.bindTo(this._contextKeyService); + this._focusedLastLineContextKey = this.rawFocusLastLineContextKey.bindTo(this._contextKeyService); + this.add(this._focusTracker.onDidFocus(() => { + this._focusedContextKey?.set(true); + this._focusedLastLineContextKey?.set(this._editorWidget.getSelection()?.positionLineNumber === this._editorWidget.getModel()?.getLineCount()); + })); + this.add(this._focusTracker.onDidBlur(() => { + this._focusedContextKey?.reset(); + this._focusedLastLineContextKey?.reset(); + })); + this._editorWidget.onDidChangeCursorPosition(() => { + console.log(this._editorWidget.getSelection()?.positionLineNumber === this._editorWidget.getModel()?.getLineCount()); + this._focusedLastLineContextKey?.set(this._editorWidget.getSelection()?.positionLineNumber === this._editorWidget.getModel()?.getLineCount()); + }); this.add(Event.runAndSubscribe(this._xterm.raw.onResize, () => this.layout())); this.add(this._configurationService.onDidChangeConfiguration(e => { From d1173ce59c051da9dd551a16b31d628d20a267be Mon Sep 17 00:00:00 2001 From: meganrogge Date: Thu, 24 Aug 2023 08:28:10 -0700 Subject: [PATCH 188/221] rm private --- .../accessibility/browser/terminalAccessibleWidget.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleWidget.ts b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleWidget.ts index f25793c1da9..b95d8814f1e 100644 --- a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleWidget.ts +++ b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleWidget.ts @@ -48,8 +48,8 @@ export abstract class TerminalAccessibleWidget extends DisposableStore { private readonly _className: string, protected readonly _instance: Pick, protected readonly _xterm: Pick & { raw: Terminal }, - private rawFocusContextKey: RawContextKey, - private rawFocusLastLineContextKey: RawContextKey, + rawFocusContextKey: RawContextKey, + rawFocusLastLineContextKey: RawContextKey, @IInstantiationService private readonly _instantiationService: IInstantiationService, @IModelService private readonly _modelService: IModelService, @IConfigurationService private readonly _configurationService: IConfigurationService, @@ -90,8 +90,8 @@ export abstract class TerminalAccessibleWidget extends DisposableStore { this._xtermElement.insertAdjacentElement('beforebegin', this._element); this._focusTracker = this.add(dom.trackFocus(this._editorContainer)); - this._focusedContextKey = this.rawFocusContextKey.bindTo(this._contextKeyService); - this._focusedLastLineContextKey = this.rawFocusLastLineContextKey.bindTo(this._contextKeyService); + this._focusedContextKey = rawFocusContextKey.bindTo(this._contextKeyService); + this._focusedLastLineContextKey = rawFocusLastLineContextKey.bindTo(this._contextKeyService); this.add(this._focusTracker.onDidFocus(() => { this._focusedContextKey?.set(true); this._focusedLastLineContextKey?.set(this._editorWidget.getSelection()?.positionLineNumber === this._editorWidget.getModel()?.getLineCount()); From 52771a40c46c2c6e982acf211c7337e7d4b36079 Mon Sep 17 00:00:00 2001 From: meganrogge Date: Thu, 24 Aug 2023 08:34:39 -0700 Subject: [PATCH 189/221] reuse var --- .../accessibility/browser/terminalAccessibleBuffer.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts index 0835367c86e..f8fc9a2c500 100644 --- a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts +++ b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer.ts @@ -110,8 +110,9 @@ export class AccessibleBufferWidget extends TerminalAccessibleWidget { } private _getCommandsWithEditorLine(): ICommandWithEditorLine[] | undefined { - const commands = this._instance.capabilities.get(TerminalCapability.CommandDetection)?.commands; - const currentCommand = this._instance.capabilities.get(TerminalCapability.CommandDetection)?.currentCommand; + const capability = this._instance.capabilities.get(TerminalCapability.CommandDetection); + const commands = capability?.commands; + const currentCommand = capability?.currentCommand; if (!commands?.length) { return; } From c0655c7c1725ad4c3494686f7be925838810f97d Mon Sep 17 00:00:00 2001 From: meganrogge Date: Thu, 24 Aug 2023 09:05:28 -0700 Subject: [PATCH 190/221] fix #188329 --- .../browser/terminal.accessibility.contribution.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminal.accessibility.contribution.ts b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminal.accessibility.contribution.ts index 96b9602e45d..0efe30d072d 100644 --- a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminal.accessibility.contribution.ts +++ b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminal.accessibility.contribution.ts @@ -117,8 +117,8 @@ registerTerminalAction({ precondition: ContextKeyExpr.or(TerminalContextKeys.processSupported, TerminalContextKeys.terminalHasBeenCreated), keybinding: [ { - primary: KeyMod.Shift | KeyCode.Tab, - secondary: [KeyMod.CtrlCmd | KeyCode.UpArrow, KeyMod.Alt | KeyCode.F2], + primary: KeyMod.CtrlCmd | KeyCode.UpArrow, + secondary: [KeyMod.Alt | KeyCode.F2], weight: KeybindingWeight.WorkbenchContrib, when: ContextKeyExpr.and(CONTEXT_ACCESSIBILITY_MODE_ENABLED, TerminalContextKeys.focus, ContextKeyExpr.or(terminalTabFocusModeContextKey, TerminalContextKeys.accessibleBufferFocus.negate())) } From f52b2d78e9f4a2b564a465fb0ba9e63f7622b513 Mon Sep 17 00:00:00 2001 From: meganrogge Date: Thu, 24 Aug 2023 09:09:59 -0700 Subject: [PATCH 191/221] Revert "fix #188329" This reverts commit c0655c7c1725ad4c3494686f7be925838810f97d. --- .../browser/terminal.accessibility.contribution.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminal.accessibility.contribution.ts b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminal.accessibility.contribution.ts index 0efe30d072d..96b9602e45d 100644 --- a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminal.accessibility.contribution.ts +++ b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminal.accessibility.contribution.ts @@ -117,8 +117,8 @@ registerTerminalAction({ precondition: ContextKeyExpr.or(TerminalContextKeys.processSupported, TerminalContextKeys.terminalHasBeenCreated), keybinding: [ { - primary: KeyMod.CtrlCmd | KeyCode.UpArrow, - secondary: [KeyMod.Alt | KeyCode.F2], + primary: KeyMod.Shift | KeyCode.Tab, + secondary: [KeyMod.CtrlCmd | KeyCode.UpArrow, KeyMod.Alt | KeyCode.F2], weight: KeybindingWeight.WorkbenchContrib, when: ContextKeyExpr.and(CONTEXT_ACCESSIBILITY_MODE_ENABLED, TerminalContextKeys.focus, ContextKeyExpr.or(terminalTabFocusModeContextKey, TerminalContextKeys.accessibleBufferFocus.negate())) } From 3bed7cfbdbde8c3370e040b9c8b8d9462a0c23b3 Mon Sep 17 00:00:00 2001 From: Henning Dieterichs Date: Thu, 24 Aug 2023 16:57:19 +0200 Subject: [PATCH 192/221] Fixes #190422 --- .../inlineCompletions/browser/commands.ts | 3 +- .../browser/inlineCompletionsHintsWidget.css | 2 +- .../browser/inlineCompletionsHintsWidget.ts | 56 ++++++++++++++----- 3 files changed, 46 insertions(+), 15 deletions(-) diff --git a/src/vs/editor/contrib/inlineCompletions/browser/commands.ts b/src/vs/editor/contrib/inlineCompletions/browser/commands.ts index 799433568e0..ac7535f9231 100644 --- a/src/vs/editor/contrib/inlineCompletions/browser/commands.ts +++ b/src/vs/editor/contrib/inlineCompletions/browser/commands.ts @@ -148,7 +148,8 @@ export class AcceptInlineCompletion extends EditorAction { InlineCompletionContextKeys.inlineSuggestionVisible, EditorContextKeys.tabMovesFocus.toNegated(), InlineCompletionContextKeys.inlineSuggestionHasIndentationLessThanTabSize, - SuggestContext.Visible.toNegated() + SuggestContext.Visible.toNegated(), + EditorContextKeys.hoverFocused.toNegated(), ), } }); diff --git a/src/vs/editor/contrib/inlineCompletions/browser/inlineCompletionsHintsWidget.css b/src/vs/editor/contrib/inlineCompletions/browser/inlineCompletionsHintsWidget.css index 642e6c51d7a..196307cc49e 100644 --- a/src/vs/editor/contrib/inlineCompletions/browser/inlineCompletionsHintsWidget.css +++ b/src/vs/editor/contrib/inlineCompletions/browser/inlineCompletionsHintsWidget.css @@ -29,7 +29,7 @@ padding: 2px 3px; } -.monaco-editor .inlineSuggestionsHints .custom-actions .action-item:nth-child(2) a { +.monaco-editor .inlineSuggestionsHints .availableSuggestionCount a { display: flex; min-width: 19px; justify-content: center; diff --git a/src/vs/editor/contrib/inlineCompletions/browser/inlineCompletionsHintsWidget.ts b/src/vs/editor/contrib/inlineCompletions/browser/inlineCompletionsHintsWidget.ts index eb9aa10b05c..0cde6e9a9b5 100644 --- a/src/vs/editor/contrib/inlineCompletions/browser/inlineCompletionsHintsWidget.ts +++ b/src/vs/editor/contrib/inlineCompletions/browser/inlineCompletionsHintsWidget.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { h } from 'vs/base/browser/dom'; -import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; +import { ActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems'; import { KeybindingLabel, unthemedKeybindingLabelOptions } from 'vs/base/browser/ui/keybindingLabel/keybindingLabel'; import { Action, IAction, Separator } from 'vs/base/common/actions'; import { equals } from 'vs/base/common/arrays'; @@ -112,10 +112,7 @@ export class InlineSuggestionHintsContentWidget extends Disposable implements IC public readonly suppressMouseDown = false; private readonly nodes = h('div.inlineSuggestionsHints', { className: this.withBorder ? '.withBorder' : '' }, [ - h('div', { style: { display: 'flex' } }, [ - h('div@actionBar', { className: 'custom-actions' }), - h('div@toolBar'), - ]) + h('div@toolBar'), ]); private createCommandAction(commandId: string, label: string, iconClassName: string): Action { @@ -173,21 +170,29 @@ export class InlineSuggestionHintsContentWidget extends Disposable implements IC ) { super(); - const actionBar = this._register(new ActionBar(this.nodes.actionBar)); - - actionBar.push(this.previousAction, { icon: true, label: false }); - actionBar.push(this.availableSuggestionCountAction); - actionBar.push(this.nextAction, { icon: true, label: false }); - this.toolBar = this._register(instantiationService.createInstance(CustomizedMenuWorkbenchToolBar, this.nodes.toolBar, MenuId.InlineSuggestionToolbar, { menuOptions: { renderShortTitle: true }, toolbarOptions: { primaryGroup: g => g.startsWith('primary') }, actionViewItemProvider: (action, options) => { - return action instanceof MenuItemAction ? instantiationService.createInstance(StatusBarViewItem, action, undefined) : undefined; + if (action instanceof MenuItemAction) { + return instantiationService.createInstance(StatusBarViewItem, action, undefined); + } + if (action === this.availableSuggestionCountAction) { + const a = new ActionViewItemWithClassName(undefined, action, { label: true, icon: false }); + a.setClass('availableSuggestionCount'); + return a; + } + return undefined; }, telemetrySource: 'InlineSuggestionToolbar', })); + this.toolBar.setPrependedPrimaryActions([ + this.previousAction, + this.availableSuggestionCountAction, + this.nextAction, + ]); + this._register(this.toolBar.onDidChangeDropdownVisibility(e => { InlineSuggestionHintsContentWidget._dropDownVisible = e; })); @@ -270,6 +275,21 @@ export class InlineSuggestionHintsContentWidget extends Disposable implements IC } } +class ActionViewItemWithClassName extends ActionViewItem { + private _className: string | undefined = undefined; + + setClass(className: string | undefined): void { + this._className = className; + } + + override render(container: HTMLElement): void { + super.render(container); + if (this._className) { + container.classList.add(this._className); + } + } +} + class StatusBarViewItem extends MenuEntryActionViewItem { protected override updateLabel() { const kb = this._keybindingService.lookupKeybinding(this._action.id, this._contextKeyService); @@ -291,6 +311,7 @@ class StatusBarViewItem extends MenuEntryActionViewItem { export class CustomizedMenuWorkbenchToolBar extends WorkbenchToolBar { private readonly menu = this._store.add(this.menuService.createMenu(this.menuId, this.contextKeyService, { emitEventsForSubmenuChanges: true })); private additionalActions: IAction[] = []; + private prependedPrimaryActions: IAction[] = []; constructor( container: HTMLElement, @@ -319,12 +340,21 @@ export class CustomizedMenuWorkbenchToolBar extends WorkbenchToolBar { ); secondary.push(...this.additionalActions); + primary.unshift(...this.prependedPrimaryActions); this.setActions(primary, secondary); } + setPrependedPrimaryActions(actions: IAction[]): void { + if (equals(this.prependedPrimaryActions, actions, (a, b) => a === b)) { + return; + } + + this.prependedPrimaryActions = actions; + this.updateToolbar(); + } + setAdditionalSecondaryActions(actions: IAction[]): void { if (equals(this.additionalActions, actions, (a, b) => a === b)) { - // don't update if the actions are the same return; } From 3fbf0442d354acd412eaee43ef8ba90bfd9ac4cb Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Thu, 24 Aug 2023 09:44:27 -0700 Subject: [PATCH 193/221] tunnels: fix forgotten event listener (#191228) Was accidentally removed removed during a PR comment followup Fixes #190859 --- src/vs/platform/tunnel/node/tunnelService.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/vs/platform/tunnel/node/tunnelService.ts b/src/vs/platform/tunnel/node/tunnelService.ts index 0894400360d..f28dc9e2271 100644 --- a/src/vs/platform/tunnel/node/tunnelService.ts +++ b/src/vs/platform/tunnel/node/tunnelService.ts @@ -19,6 +19,7 @@ import { IAddressProvider, IConnectionOptions, connectRemoteAgentTunnel } from ' import { IRemoteSocketFactoryService } from 'vs/platform/remote/common/remoteSocketFactoryService'; import { ISignService } from 'vs/platform/sign/common/sign'; import { AbstractTunnelService, ISharedTunnelsService, ITunnelProvider, ITunnelService, RemoteTunnel, TunnelPrivacyId, isAllInterfaces, isLocalhost, isPortPrivileged, isTunnelProvider } from 'vs/platform/tunnel/common/tunnel'; +import { VSBuffer } from 'vs/base/common/buffer'; async function createRemoteTunnel(options: IConnectionOptions, defaultTunnelHost: string, tunnelRemoteHost: string, tunnelRemotePort: number, tunnelLocalPort?: number): Promise { let readyTunnel: NodeRemoteTunnel | undefined; @@ -159,6 +160,7 @@ export class NodeRemoteTunnel extends Disposable implements RemoteTunnel { remoteSocket.onClose(() => localSocket.destroy()); remoteSocket.onEnd(() => localSocket.end()); remoteSocket.onData(d => localSocket.write(d.buffer)); + localSocket.on('data', d => remoteSocket.write(VSBuffer.wrap(d))); localSocket.resume(); } From 6acb0ecd042d3db44604497e3ab82644bd0787e7 Mon Sep 17 00:00:00 2001 From: Henning Dieterichs Date: Thu, 24 Aug 2023 18:53:22 +0200 Subject: [PATCH 194/221] Fixes #188070 --- .../threadedBackgroundTokenizerFactory.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/services/textMate/browser/backgroundTokenization/threadedBackgroundTokenizerFactory.ts b/src/vs/workbench/services/textMate/browser/backgroundTokenization/threadedBackgroundTokenizerFactory.ts index b121441fd78..9558ffdd75e 100644 --- a/src/vs/workbench/services/textMate/browser/backgroundTokenization/threadedBackgroundTokenizerFactory.ts +++ b/src/vs/workbench/services/textMate/browser/backgroundTokenization/threadedBackgroundTokenizerFactory.ts @@ -63,7 +63,7 @@ export class ThreadedBackgroundTokenizerFactory implements IDisposable { const controllerContainer = this._getWorkerProxy().then((workerProxy) => { if (store.isDisposed || !workerProxy) { return undefined; } - const controllerContainer = { controller: undefined as undefined | TextMateWorkerTokenizerController }; + const controllerContainer = { controller: undefined as undefined | TextMateWorkerTokenizerController, worker: this._worker }; store.add(keepAliveWhenAttached(textModel, () => { const controller = new TextMateWorkerTokenizerController(textModel, workerProxy, this._languageService.languageIdCodec, tokenStore, this._configurationService, maxTokenizationLineLength); controllerContainer.controller = controller; @@ -82,10 +82,12 @@ export class ThreadedBackgroundTokenizerFactory implements IDisposable { store.dispose(); }, requestTokens: async (startLineNumber, endLineNumberExclusive) => { - const controller = (await controllerContainer)?.controller; - if (controller) { - // If there is no controller, the model has been detached in the meantime - controller.requestTokens(startLineNumber, endLineNumberExclusive); + const container = await controllerContainer; + + // If there is no controller, the model has been detached in the meantime. + // Only request the proxy object if the worker is the same! + if (container?.controller && container.worker === this._worker) { + container.controller.requestTokens(startLineNumber, endLineNumberExclusive); } }, reportMismatchingTokens: (lineNumber) => { From c520db561ce3ffbb9d9507f0a61f4cd375609c17 Mon Sep 17 00:00:00 2001 From: meganrogge Date: Thu, 24 Aug 2023 10:52:37 -0700 Subject: [PATCH 195/221] fix #189864 --- .../browser/accessibilityContributions.ts | 2 +- .../accessibility/browser/accessibleView.ts | 25 ++++++++++--------- .../browser/accessibleViewActions.ts | 4 +-- .../browser/actions/chatAccessibilityHelp.ts | 2 +- .../browser/accessibility/accessibility.css | 2 +- .../codeEditor/browser/diffEditorHelper.ts | 2 +- .../notebook/browser/notebookAccessibility.ts | 2 +- .../browser/terminalAccessibilityHelp.ts | 16 ++++++------ 8 files changed, 29 insertions(+), 26 deletions(-) diff --git a/src/vs/workbench/contrib/accessibility/browser/accessibilityContributions.ts b/src/vs/workbench/contrib/accessibility/browser/accessibilityContributions.ts index 1baf82143d4..cfab22c7cc3 100644 --- a/src/vs/workbench/contrib/accessibility/browser/accessibilityContributions.ts +++ b/src/vs/workbench/contrib/accessibility/browser/accessibilityContributions.ts @@ -101,7 +101,7 @@ class AccessibilityHelpProvider implements IAccessibleContentProvider { } else { content.push(this._descriptionForCommand(ToggleTabFocusModeAction.ID, AccessibilityHelpNLS.tabFocusModeOffMsg, AccessibilityHelpNLS.tabFocusModeOffMsgNoKb)); } - return content.join('\n'); + return content.join('\n\n'); } } diff --git a/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts b/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts index 68302f41952..617c87028f8 100644 --- a/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts +++ b/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts @@ -3,13 +3,17 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { EventType, addDisposableListener } from 'vs/base/browser/dom'; import { IKeyboardEvent, StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { ActionsOrientation } from 'vs/base/browser/ui/actionbar/actionbar'; import { alert } from 'vs/base/browser/ui/aria/aria'; +import { IAction } from 'vs/base/common/actions'; +import { Codicon } from 'vs/base/common/codicons'; import { KeyCode } from 'vs/base/common/keyCodes'; import { Disposable, DisposableStore, IDisposable } from 'vs/base/common/lifecycle'; import { marked } from 'vs/base/common/marked/marked'; import { isMacintosh } from 'vs/base/common/platform'; +import { ThemeIcon } from 'vs/base/common/themables'; import { URI } from 'vs/base/common/uri'; import { IEditorConstructionOptions } from 'vs/editor/browser/config/editorConfiguration'; import { EditorExtensionsRegistry } from 'vs/editor/browser/editorExtensions'; @@ -20,6 +24,7 @@ import { AccessibilityHelpNLS } from 'vs/editor/common/standaloneStrings'; import { CodeActionController } from 'vs/editor/contrib/codeAction/browser/codeActionController'; import { localize } from 'vs/nls'; import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; +import { createAndFillInActionBarActions } from 'vs/platform/actions/browser/menuEntryActionViewItem'; import { WorkbenchToolBar } from 'vs/platform/actions/browser/toolbar'; import { IMenuService, MenuId } from 'vs/platform/actions/common/actions'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; @@ -31,14 +36,9 @@ import { ILayoutService } from 'vs/platform/layout/browser/layoutService'; import { IOpenerService } from 'vs/platform/opener/common/opener'; import { IPickerQuickAccessItem } from 'vs/platform/quickinput/browser/pickerQuickAccess'; import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; -import { AccessibilityCommandId } from 'vs/workbench/contrib/accessibility/common/accessibilityCommands'; import { AccessibilityVerbositySettingId, accessibilityHelpIsShown, accessibleViewCurrentProviderId, accessibleViewGoToSymbolSupported, accessibleViewIsShown, accessibleViewSupportsNavigation, accessibleViewVerbosityEnabled } from 'vs/workbench/contrib/accessibility/browser/accessibilityConfiguration'; +import { AccessibilityCommandId } from 'vs/workbench/contrib/accessibility/common/accessibilityCommands'; import { getSimpleEditorOptions } from 'vs/workbench/contrib/codeEditor/browser/simpleEditorOptions'; -import { IAction } from 'vs/base/common/actions'; -import { createAndFillInActionBarActions } from 'vs/platform/actions/browser/menuEntryActionViewItem'; -import { Codicon } from 'vs/base/common/codicons'; -import { ThemeIcon } from 'vs/base/common/themables'; -import { addDisposableListener, EventType } from 'vs/base/browser/dom'; const enum DIMENSIONS { MAX_WIDTH = 600 @@ -108,6 +108,7 @@ class AccessibleView extends Disposable { private _editorContainer: HTMLElement; private _currentProvider: IAccessibleContentProvider | undefined; private readonly _toolbar: WorkbenchToolBar; + private _currentContent: string | undefined; constructor( @IOpenerService private readonly _openerService: IOpenerService, @@ -217,10 +218,10 @@ class AccessibleView extends Disposable { } getSymbols(): IAccessibleViewSymbol[] | undefined { - if (!this._currentProvider) { + if (!this._currentProvider || !this._currentContent) { return; } - const tokens = this._currentProvider.options.language && this._currentProvider.options.language !== 'markdown' ? this._currentProvider.getSymbols?.() : marked.lexer(this._currentProvider.provideContent()); + const tokens = this._currentProvider.options.language && this._currentProvider.options.language !== 'markdown' ? this._currentProvider.getSymbols?.() : marked.lexer(this._currentContent); if (!tokens) { return; } @@ -299,7 +300,7 @@ class AccessibleView extends Disposable { } this._updateContextKeys(provider, true); const value = this._configurationService.getValue(provider.verbositySettingKey); - const readMoreLink = provider.options.readMoreUrl ? localize("openDoc", "\nPress H now to open a browser window with more information related to accessibility.\n") : ''; + const readMoreLink = provider.options.readMoreUrl ? localize("openDoc", "\n\nPress H now to open a browser window with more information related to accessibility.\n\n") : ''; let disableHelpHint = ''; if (provider.options.type === AccessibleViewType.Help && !!value) { disableHelpHint = this._getDisableVerbosityHint(provider.verbositySettingKey); @@ -321,9 +322,9 @@ class AccessibleView extends Disposable { } } - const fragment = message + provider.provideContent() + readMoreLink + disableHelpHint + localize('exit-tip', '\nExit this dialog via the Escape key.'); + this._currentContent = message + provider.provideContent() + readMoreLink + disableHelpHint + localize('exit-tip', '\n\nExit this dialog via the Escape key.'); - this._getTextModel(URI.from({ path: `accessible-view-${provider.verbositySettingKey}`, scheme: 'accessible-view', fragment })).then((model) => { + this._getTextModel(URI.from({ path: `accessible-view-${provider.verbositySettingKey}`, scheme: 'accessible-view', fragment: this._currentContent })).then((model) => { if (!model) { return; } @@ -424,7 +425,7 @@ class AccessibleView extends Disposable { if (!this._currentProvider) { return false; } - return this._currentProvider.options.language === 'markdown' || this._currentProvider.options.language === undefined || !!this._currentProvider.getSymbols; + return this._currentProvider.options.type === AccessibleViewType.Help || this._currentProvider.options.language === 'markdown' || this._currentProvider.options.language === undefined || !!this._currentProvider.getSymbols; } public showAccessibleViewHelp(): void { diff --git a/src/vs/workbench/contrib/accessibility/browser/accessibleViewActions.ts b/src/vs/workbench/contrib/accessibility/browser/accessibleViewActions.ts index c62bcf7782b..9133dc3fd82 100644 --- a/src/vs/workbench/contrib/accessibility/browser/accessibleViewActions.ts +++ b/src/vs/workbench/contrib/accessibility/browser/accessibleViewActions.ts @@ -84,7 +84,7 @@ class AccessibleViewGoToSymbolAction extends Action2 { constructor() { super({ id: AccessibilityCommandId.GoToSymbol, - precondition: ContextKeyExpr.and(accessibleViewIsShown, accessibleViewGoToSymbolSupported), + precondition: ContextKeyExpr.and(ContextKeyExpr.or(accessibleViewIsShown, accessibilityHelpIsShown), accessibleViewGoToSymbolSupported), keybinding: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KeyO, secondary: [KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.Period], @@ -95,7 +95,7 @@ class AccessibleViewGoToSymbolAction extends Action2 { commandPalette, { ...accessibleViewMenu, - when: ContextKeyExpr.and(accessibleViewIsShown, accessibleViewSupportsNavigation), + when: ContextKeyExpr.and(ContextKeyExpr.or(accessibleViewIsShown, accessibilityHelpIsShown), accessibleViewGoToSymbolSupported), } ], title: localize('editor.action.accessibleViewGoToSymbol', "Go To Symbol in Accessible View") diff --git a/src/vs/workbench/contrib/chat/browser/actions/chatAccessibilityHelp.ts b/src/vs/workbench/contrib/chat/browser/actions/chatAccessibilityHelp.ts index f8c40b935f7..e277b372021 100644 --- a/src/vs/workbench/contrib/chat/browser/actions/chatAccessibilityHelp.ts +++ b/src/vs/workbench/contrib/chat/browser/actions/chatAccessibilityHelp.ts @@ -45,7 +45,7 @@ export function getAccessibilityHelpText(accessor: ServicesAccessor, type: 'pane content.push(localize('inlineChat.toolbar', "Use tab to reach conditional parts like commands, status, message responses and more.")); } content.push(localize('chat.audioCues', "Audio cues can be changed via settings with a prefix of audioCues.chat. By default, if a request takes more than 4 seconds, you will hear an audio cue indicating that progress is still occurring.")); - return content.join('\n'); + return content.join('\n\n'); } function descriptionForCommand(commandId: string, msg: string, noKbMsg: string, keybindingService: IKeybindingService): string { diff --git a/src/vs/workbench/contrib/codeEditor/browser/accessibility/accessibility.css b/src/vs/workbench/contrib/codeEditor/browser/accessibility/accessibility.css index 25fcb4b03d8..2e0a1c51753 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/accessibility/accessibility.css +++ b/src/vs/workbench/contrib/codeEditor/browser/accessibility/accessibility.css @@ -11,7 +11,7 @@ border: 2px solid var(--vscode-focusBorder); border-radius: 6px; margin-top: -1px; - z-index: 2550; + z-index: 2540; } .accessible-view-container .actions-container { diff --git a/src/vs/workbench/contrib/codeEditor/browser/diffEditorHelper.ts b/src/vs/workbench/contrib/codeEditor/browser/diffEditorHelper.ts index 1e0d06ff9b8..22148696b72 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/diffEditorHelper.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/diffEditorHelper.ts @@ -107,7 +107,7 @@ function createScreenReaderHelp(): IDisposable { localize('msg1', "You are in a diff editor."), localize('msg2', "Press {0} or {1} to view the next or previous diff in the diff review mode that is optimized for screen readers.", next, previous), localize('msg3', "To control which audio cues should be played, the following settings can be configured: {0}.", keys.join(', ')), - ].join('\n'), + ].join('\n\n'), onClose: () => { codeEditor.focus(); }, diff --git a/src/vs/workbench/contrib/notebook/browser/notebookAccessibility.ts b/src/vs/workbench/contrib/notebook/browser/notebookAccessibility.ts index 790e9e8bdc3..a019db5693e 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookAccessibility.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookAccessibility.ts @@ -34,7 +34,7 @@ export function getAccessibilityHelpText(accessor: ServicesAccessor): string { content.push(localize('notebook.changeCellType', 'The Change Cell to Code/Markdown commands are used to switch between cell types.')); - return content.join('\n'); + return content.join('\n\n'); } function descriptionForCommand(commandId: string, msg: string, noKbMsg: string, keybindingService: IKeybindingService): string { diff --git a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibilityHelp.ts b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibilityHelp.ts index d3a0e3a592c..2504d461fb2 100644 --- a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibilityHelp.ts +++ b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibilityHelp.ts @@ -75,18 +75,20 @@ export class TerminalAccessibleContentProvider extends Disposable implements IAc content.push(localize('commandPromptMigration', "Consider using powershell instead of command prompt for an improved experience")); } if (this._hasShellIntegration) { - content.push(localize('shellIntegration', "The terminal has a feature called shell integration that offers an enhanced experience and provides useful commands for screen readers such as:")); - content.push('- ' + this._descriptionForCommand(TerminalCommandId.AccessibleBufferGoToNextCommand, localize('goToNextCommand', 'Go to Next Command ({0})'), localize('goToNextCommandNoKb', 'Go to Next Command is currently not triggerable by a keybinding.'))); - content.push('- ' + this._descriptionForCommand(TerminalCommandId.AccessibleBufferGoToPreviousCommand, localize('goToPreviousCommand', 'Go to Previous Command ({0})'), localize('goToPreviousCommandNoKb', 'Go to Previous Command is currently not triggerable by a keybinding.'))); - content.push('- ' + this._descriptionForCommand(TerminalCommandId.NavigateAccessibleBuffer, localize('navigateAccessibleBuffer', 'Navigate Accessible Buffer ({0})'), localize('navigateAccessibleBufferNoKb', 'Navigate Accessible Buffer is currently not triggerable by a keybinding.'))); - content.push('- ' + this._descriptionForCommand(TerminalCommandId.RunRecentCommand, localize('runRecentCommand', 'Run Recent Command ({0})'), localize('runRecentCommandNoKb', 'Run Recent Command is currently not triggerable by a keybinding.'))); - content.push('- ' + this._descriptionForCommand(TerminalCommandId.GoToRecentDirectory, localize('goToRecentDirectory', 'Go to Recent Directory ({0})'), localize('goToRecentDirectoryNoKb', 'Go to Recent Directory is currently not triggerable by a keybinding.'))); + const shellIntegrationCommandList = []; + shellIntegrationCommandList.push(localize('shellIntegration', "The terminal has a feature called shell integration that offers an enhanced experience and provides useful commands for screen readers such as:")); + shellIntegrationCommandList.push('- ' + this._descriptionForCommand(TerminalCommandId.AccessibleBufferGoToNextCommand, localize('goToNextCommand', 'Go to Next Command ({0})'), localize('goToNextCommandNoKb', 'Go to Next Command is currently not triggerable by a keybinding.'))); + shellIntegrationCommandList.push('- ' + this._descriptionForCommand(TerminalCommandId.AccessibleBufferGoToPreviousCommand, localize('goToPreviousCommand', 'Go to Previous Command ({0})'), localize('goToPreviousCommandNoKb', 'Go to Previous Command is currently not triggerable by a keybinding.'))); + shellIntegrationCommandList.push('- ' + this._descriptionForCommand(TerminalCommandId.NavigateAccessibleBuffer, localize('navigateAccessibleBuffer', 'Navigate Accessible Buffer ({0})'), localize('navigateAccessibleBufferNoKb', 'Navigate Accessible Buffer is currently not triggerable by a keybinding.'))); + shellIntegrationCommandList.push('- ' + this._descriptionForCommand(TerminalCommandId.RunRecentCommand, localize('runRecentCommand', 'Run Recent Command ({0})'), localize('runRecentCommandNoKb', 'Run Recent Command is currently not triggerable by a keybinding.'))); + shellIntegrationCommandList.push('- ' + this._descriptionForCommand(TerminalCommandId.GoToRecentDirectory, localize('goToRecentDirectory', 'Go to Recent Directory ({0})'), localize('goToRecentDirectoryNoKb', 'Go to Recent Directory is currently not triggerable by a keybinding.'))); + content.push(shellIntegrationCommandList.join('\n')); } else { content.push(this._descriptionForCommand(TerminalCommandId.RunRecentCommand, localize('goToRecentDirectoryNoShellIntegration', 'The Go to Recent Directory command ({0}) enables screen readers to easily navigate to a directory that has been used in the terminal.'), localize('goToRecentDirectoryNoKbNoShellIntegration', 'The Go to Recent Directory command enables screen readers to easily navigate to a directory that has been used in the terminal and is currently not triggerable by a keybinding.'))); } content.push(this._descriptionForCommand(TerminalCommandId.OpenDetectedLink, localize('openDetectedLink', 'The Open Detected Link ({0}) command enables screen readers to easily open links found in the terminal.'), localize('openDetectedLinkNoKb', 'The Open Detected Link command enables screen readers to easily open links found in the terminal and is currently not triggerable by a keybinding.'))); content.push(this._descriptionForCommand(TerminalCommandId.NewWithProfile, localize('newWithProfile', 'The Create New Terminal (With Profile) ({0}) command allows for easy terminal creation using a specific profile.'), localize('newWithProfileNoKb', 'The Create New Terminal (With Profile) command allows for easy terminal creation using a specific profile and is currently not triggerable by a keybinding.'))); content.push(localize('accessibilitySettings', 'Access accessibility settings such as `terminal.integrated.tabFocusMode` via the Preferences: Open Accessibility Settings command.')); - return content.join('\n'); + return content.join('\n\n'); } } From ac0d0a89c83d38cc090c70d3b9059239f4fd223f Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Thu, 24 Aug 2023 10:53:05 -0700 Subject: [PATCH 196/221] cli: adopt latest devtunnels for ipv6 forwarding support (#191236) --- cli/Cargo.lock | 2 +- cli/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cli/Cargo.lock b/cli/Cargo.lock index a67cc7cf3bd..34627da135b 100644 --- a/cli/Cargo.lock +++ b/cli/Cargo.lock @@ -2471,7 +2471,7 @@ dependencies = [ [[package]] name = "tunnels" version = "0.1.0" -source = "git+https://github.com/microsoft/dev-tunnels?rev=2621784a9ad72aa39500372391332a14bad581a3#2621784a9ad72aa39500372391332a14bad581a3" +source = "git+https://github.com/microsoft/dev-tunnels?rev=3141ad7be00e18c4231f7c4fb6c11f9219ac49af#3141ad7be00e18c4231f7c4fb6c11f9219ac49af" dependencies = [ "async-trait", "chrono", diff --git a/cli/Cargo.toml b/cli/Cargo.toml index 18f18069c1f..50fad68a8a4 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -34,7 +34,7 @@ serde_bytes = "0.11.9" chrono = { version = "0.4.26", features = ["serde", "std", "clock"], default-features = false } gethostname = "0.4.3" libc = "0.2.144" -tunnels = { git = "https://github.com/microsoft/dev-tunnels", rev = "2621784a9ad72aa39500372391332a14bad581a3", default-features = false, features = ["connections"] } +tunnels = { git = "https://github.com/microsoft/dev-tunnels", rev = "3141ad7be00e18c4231f7c4fb6c11f9219ac49af", default-features = false, features = ["connections"] } keyring = { version = "2.0.3", default-features = false, features = ["linux-secret-service-rt-tokio-crypto-openssl"] } dialoguer = "0.10.4" hyper = { version = "0.14.26", features = ["server", "http1", "runtime"] } From 7c205af18101b8b0a3325de3cda08792f8120715 Mon Sep 17 00:00:00 2001 From: meganrogge Date: Thu, 24 Aug 2023 10:57:28 -0700 Subject: [PATCH 197/221] make sure go to symbol works for help menu default actions --- .../contrib/accessibility/browser/accessibleView.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts b/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts index 617c87028f8..fd562e9e189 100644 --- a/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts +++ b/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts @@ -258,7 +258,10 @@ class AccessibleView extends Disposable { } showSymbol(provider: IAccessibleContentProvider, symbol: IAccessibleViewSymbol): void { - const index = provider.provideContent().split('\n').findIndex(line => line.includes(symbol.info.split('\n')[0]) || (symbol.firstListItem && line.includes(symbol.firstListItem))) ?? -1; + if (!this._currentContent) { + return; + } + const index = this._currentContent.split('\n').findIndex(line => line.includes(symbol.info.split('\n')[0]) || (symbol.firstListItem && line.includes(symbol.firstListItem))) ?? -1; if (index >= 0) { this.show(provider); this._editorWidget.revealLine(index + 1); From ff5ec02d95db113257519757b168dfa8c841c7db Mon Sep 17 00:00:00 2001 From: meganrogge Date: Thu, 24 Aug 2023 11:05:40 -0700 Subject: [PATCH 198/221] move setting of context key to fix issue on first invocation --- .../workbench/contrib/accessibility/browser/accessibleView.ts | 2 +- .../contrib/codeEditor/browser/accessibility/accessibility.css | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts b/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts index fd562e9e189..33deac70738 100644 --- a/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts +++ b/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts @@ -301,7 +301,6 @@ class AccessibleView extends Disposable { this._currentProvider = provider; this._accessibleViewCurrentProviderId.set(provider.verbositySettingKey.replaceAll('accessibility.verbosity.', '')); } - this._updateContextKeys(provider, true); const value = this._configurationService.getValue(provider.verbositySettingKey); const readMoreLink = provider.options.readMoreUrl ? localize("openDoc", "\n\nPress H now to open a browser window with more information related to accessibility.\n\n") : ''; let disableHelpHint = ''; @@ -326,6 +325,7 @@ class AccessibleView extends Disposable { } this._currentContent = message + provider.provideContent() + readMoreLink + disableHelpHint + localize('exit-tip', '\n\nExit this dialog via the Escape key.'); + this._updateContextKeys(provider, true); this._getTextModel(URI.from({ path: `accessible-view-${provider.verbositySettingKey}`, scheme: 'accessible-view', fragment: this._currentContent })).then((model) => { if (!model) { diff --git a/src/vs/workbench/contrib/codeEditor/browser/accessibility/accessibility.css b/src/vs/workbench/contrib/codeEditor/browser/accessibility/accessibility.css index 2e0a1c51753..25fcb4b03d8 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/accessibility/accessibility.css +++ b/src/vs/workbench/contrib/codeEditor/browser/accessibility/accessibility.css @@ -11,7 +11,7 @@ border: 2px solid var(--vscode-focusBorder); border-radius: 6px; margin-top: -1px; - z-index: 2540; + z-index: 2550; } .accessible-view-container .actions-container { From 49d8caf441662bc80913c4609ab4882ee31af418 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 24 Aug 2023 20:17:33 +0200 Subject: [PATCH 199/221] voice - log errors --- .../node/voiceRecognitionService.ts | 56 +++++++++++-------- 1 file changed, 32 insertions(+), 24 deletions(-) diff --git a/src/vs/platform/voiceRecognition/node/voiceRecognitionService.ts b/src/vs/platform/voiceRecognition/node/voiceRecognitionService.ts index fdcd3ac332d..a63b58f6224 100644 --- a/src/vs/platform/voiceRecognition/node/voiceRecognitionService.ts +++ b/src/vs/platform/voiceRecognition/node/voiceRecognitionService.ts @@ -47,33 +47,41 @@ export class VoiceRecognitionService implements IVoiceRecognitionService { const now = Date.now(); - const voiceModule: { - transcribe: ( - audioBuffer: { channelCount: 1; samplingRate: 16000; bitDepth: 16; channelData: Float32Array }, - options: { - language: string | 'auto'; - suppressNonSpeechTokens: boolean; - signal: AbortSignal; - } - ) => Promise; - } = require.__$__nodeRequire(modulePath); + this.logService.info(`[voice] transcribe(${channelData.length}): Getting module from ${modulePath}`); - const abortController = new AbortController(); - cancellation.onCancellationRequested(() => abortController.abort()); + try { + const voiceModule: { + transcribe: ( + audioBuffer: { channelCount: 1; samplingRate: 16000; bitDepth: 16; channelData: Float32Array }, + options: { + language: string | 'auto'; + suppressNonSpeechTokens: boolean; + signal: AbortSignal; + } + ) => Promise; + } = require.__$__nodeRequire(modulePath); - const text = await voiceModule.transcribe({ - samplingRate: 16000, - bitDepth: 16, - channelCount: 1, - channelData - }, { - language: 'en', - suppressNonSpeechTokens: true, - signal: abortController.signal - }); + const abortController = new AbortController(); + cancellation.onCancellationRequested(() => abortController.abort()); - this.logService.info(`[voice] transcribe(${channelData.length}): End (text: "${text}", took: ${Date.now() - now}ms)`); + const text = await voiceModule.transcribe({ + samplingRate: 16000, + bitDepth: 16, + channelCount: 1, + channelData + }, { + language: 'en', + suppressNonSpeechTokens: true, + signal: abortController.signal + }); - return text; + this.logService.info(`[voice] transcribe(${channelData.length}): End (text: "${text}", took: ${Date.now() - now}ms)`); + + return text; + } catch (error) { + this.logService.error(`[voice] transcribe(${channelData.length}): Failed (error: "${error}", took: ${Date.now() - now}ms)`); + + throw error; + } } } From 7a860fb4f5288dabd2b2dc88570a0800a963b322 Mon Sep 17 00:00:00 2001 From: rebornix Date: Thu, 24 Aug 2023 11:43:01 -0700 Subject: [PATCH 200/221] Fix tests --- .../test/browser/notebookKernelHistory.test.ts | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/notebook/test/browser/notebookKernelHistory.test.ts b/src/vs/workbench/contrib/notebook/test/browser/notebookKernelHistory.test.ts index bb7e0967612..52eadf224ae 100644 --- a/src/vs/workbench/contrib/notebook/test/browser/notebookKernelHistory.test.ts +++ b/src/vs/workbench/contrib/notebook/test/browser/notebookKernelHistory.test.ts @@ -18,7 +18,7 @@ import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/no import { PLAINTEXT_LANGUAGE_ID } from 'vs/editor/common/languages/modesRegistry'; import { IMenu, IMenuService } from 'vs/platform/actions/common/actions'; import { NotebookKernelHistoryService } from 'vs/workbench/contrib/notebook/browser/services/notebookKernelHistoryServiceImpl'; -import { IStorageService, IWillSaveStateEvent, StorageScope } from 'vs/platform/storage/common/storage'; +import { IApplicationStorageValueChangeEvent, IProfileStorageValueChangeEvent, IStorageService, IStorageValueChangeEvent, IWillSaveStateEvent, IWorkspaceStorageValueChangeEvent, StorageScope } from 'vs/platform/storage/common/storage'; import { INotebookLoggingService } from 'vs/workbench/contrib/notebook/common/notebookLoggingService'; suite('NotebookKernelHistoryService', () => { @@ -70,6 +70,12 @@ suite('NotebookKernelHistoryService', () => { instantiationService.stub(IStorageService, new class extends mock() { override onWillSaveState: Event = Event.None; + override onDidChangeValue(scope: StorageScope.WORKSPACE, key: string | undefined, disposable: DisposableStore): Event; + override onDidChangeValue(scope: StorageScope.PROFILE, key: string | undefined, disposable: DisposableStore): Event; + override onDidChangeValue(scope: StorageScope.APPLICATION, key: string | undefined, disposable: DisposableStore): Event; + override onDidChangeValue(scope: StorageScope, key: string | undefined, disposable: DisposableStore): Event { + return Event.None; + } override get(key: string, scope: StorageScope, fallbackValue: string): string; override get(key: string, scope: StorageScope, fallbackValue?: string | undefined): string | undefined; override get(key: unknown, scope: unknown, fallbackValue?: unknown): string | undefined { @@ -119,6 +125,12 @@ suite('NotebookKernelHistoryService', () => { instantiationService.stub(IStorageService, new class extends mock() { override onWillSaveState: Event = Event.None; + override onDidChangeValue(scope: StorageScope.WORKSPACE, key: string | undefined, disposable: DisposableStore): Event; + override onDidChangeValue(scope: StorageScope.PROFILE, key: string | undefined, disposable: DisposableStore): Event; + override onDidChangeValue(scope: StorageScope.APPLICATION, key: string | undefined, disposable: DisposableStore): Event; + override onDidChangeValue(scope: StorageScope, key: string | undefined, disposable: DisposableStore): Event { + return Event.None; + } override get(key: string, scope: StorageScope, fallbackValue: string): string; override get(key: string, scope: StorageScope, fallbackValue?: string | undefined): string | undefined; override get(key: unknown, scope: unknown, fallbackValue?: unknown): string | undefined { From 794400449fb70a6ff317410152d5997fdac35c35 Mon Sep 17 00:00:00 2001 From: meganrogge Date: Thu, 24 Aug 2023 11:55:43 -0700 Subject: [PATCH 201/221] fix #191238 --- .../contrib/accessibility/browser/accessibleView.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts b/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts index 33deac70738..506af0bfe15 100644 --- a/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts +++ b/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts @@ -187,6 +187,7 @@ class AccessibleView extends Disposable { if (!showAccessibleViewHelp) { this._currentProvider = undefined; this._accessibleViewCurrentProviderId.reset(); + this._updateContextKeys(provider!, false); } } }; @@ -267,6 +268,7 @@ class AccessibleView extends Disposable { this._editorWidget.revealLine(index + 1); this._editorWidget.setSelection({ startLineNumber: index + 1, startColumn: 1, endLineNumber: index + 1, endColumn: 1 }); } + this._updateContextKeys(provider, true); } disableHint(): void { @@ -280,10 +282,10 @@ class AccessibleView extends Disposable { private _updateContextKeys(provider: IAccessibleContentProvider, shown: boolean): void { if (provider.options.type === AccessibleViewType.Help) { this._accessiblityHelpIsShown.set(shown); - this._accessibleViewIsShown.set(!shown); + this._accessibleViewIsShown.reset(); } else { this._accessibleViewIsShown.set(shown); - this._accessiblityHelpIsShown.set(!shown); + this._accessiblityHelpIsShown.reset(); } if (provider.next && provider.previous) { this._accessibleViewSupportsNavigation.set(true); From ecb0c80fc1da718cabb863409897d941bf18aa49 Mon Sep 17 00:00:00 2001 From: Logan Ramos Date: Thu, 24 Aug 2023 12:53:41 -0700 Subject: [PATCH 202/221] Bump extension telemetry module (#191237) * Bump extension telemetry module * Fix webpack --- extensions/git/package.json | 2 +- extensions/git/yarn.lock | 393 ++++++++++++----- extensions/github-authentication/package.json | 2 +- extensions/github-authentication/yarn.lock | 393 ++++++++++++----- extensions/github/package.json | 2 +- extensions/github/yarn.lock | 398 +++++++++++++----- .../markdown-language-features/package.json | 2 +- .../markdown-language-features/yarn.lock | 376 ++++++++++++----- extensions/media-preview/package.json | 2 +- extensions/media-preview/yarn.lock | 393 ++++++++++++----- extensions/merge-conflict/package.json | 2 +- extensions/merge-conflict/yarn.lock | 393 ++++++++++++----- .../microsoft-authentication/package.json | 2 +- extensions/microsoft-authentication/yarn.lock | 393 ++++++++++++----- extensions/shared.webpack.config.js | 2 + extensions/simple-browser/package.json | 2 +- extensions/simple-browser/yarn.lock | 393 ++++++++++++----- .../typescript-language-features/package.json | 2 +- .../typescript-language-features/yarn.lock | 381 ++++++++++++----- 19 files changed, 2635 insertions(+), 898 deletions(-) diff --git a/extensions/git/package.json b/extensions/git/package.json index d7d241e0aab..105491916ca 100644 --- a/extensions/git/package.json +++ b/extensions/git/package.json @@ -3005,7 +3005,7 @@ }, "dependencies": { "@joaomoreno/unique-names-generator": "^5.1.0", - "@vscode/extension-telemetry": "0.7.5", + "@vscode/extension-telemetry": "^0.8.4", "@vscode/iconv-lite-umd": "0.7.0", "byline": "^5.0.0", "file-type": "16.5.4", diff --git a/extensions/git/yarn.lock b/extensions/git/yarn.lock index 6be6a6b4e43..bb3a09d947c 100644 --- a/extensions/git/yarn.lock +++ b/extensions/git/yarn.lock @@ -17,7 +17,16 @@ "@azure/abort-controller" "^1.0.0" tslib "^2.2.0" -"@azure/core-rest-pipeline@^1.10.0": +"@azure/core-auth@^1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@azure/core-auth/-/core-auth-1.5.0.tgz#a41848c5c31cb3b7c84c409885267d55a2c92e44" + integrity sha512-udzoBuYG1VBoHVohDTrvKjyzel34zt77Bhp7dQntVGGD0ehVq48owENbBG8fIgkHRNUBQH5k1r0hpoMu5L8+kw== + dependencies: + "@azure/abort-controller" "^1.0.0" + "@azure/core-util" "^1.1.0" + tslib "^2.2.0" + +"@azure/core-rest-pipeline@1.10.1": version "1.10.1" resolved "https://registry.yarnpkg.com/@azure/core-rest-pipeline/-/core-rest-pipeline-1.10.1.tgz#348290847ca31b9eecf9cf5de7519aaccdd30968" integrity sha512-Kji9k6TOFRDB5ZMTw8qUf2IJ+CeJtsuMdAHox9eqpTf1cefiNMpzrfnF6sINEBZJsaVaWgQ0o48B6kcUH68niA== @@ -33,13 +42,21 @@ tslib "^2.2.0" uuid "^8.3.0" -"@azure/core-tracing@^1.0.1": +"@azure/core-tracing@^1.0.0", "@azure/core-tracing@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@azure/core-tracing/-/core-tracing-1.0.1.tgz#352a38cbea438c4a83c86b314f48017d70ba9503" integrity sha512-I5CGMoLtX+pI17ZdiFJZgxMJApsK6jjfm85hpgp3oazCdq5Wxgh4wMr7ge/TTWW1B5WBuvIOI1fMU/FrOAMKrw== dependencies: tslib "^2.2.0" +"@azure/core-util@1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@azure/core-util/-/core-util-1.2.0.tgz#3499deba1fc36dda6f1912b791809b6f15d4a392" + integrity sha512-ffGIw+Qs8bNKNLxz5UPkz4/VBM/EZY07mPve1ZYFqYUdPwFqRj0RPk0U7LZMOfT7GCck9YjuT1Rfp1PApNl1ng== + dependencies: + "@azure/abort-controller" "^1.0.0" + tslib "^2.2.0" + "@azure/core-util@^1.0.0": version "1.1.1" resolved "https://registry.yarnpkg.com/@azure/core-util/-/core-util-1.1.1.tgz#8f87b3dd468795df0f0849d9f096c3e7b29452c1" @@ -48,6 +65,14 @@ "@azure/abort-controller" "^1.0.0" tslib "^2.2.0" +"@azure/core-util@^1.1.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@azure/core-util/-/core-util-1.4.0.tgz#c120a56b3e48a9e4d20619a0b00268ae9de891c7" + integrity sha512-eGAyJpm3skVQoLiRqm/xPa+SXi/NPDdSHMxbRAz2lSprd+Zs+qrpQGQQ2VQ3Nttu+nSZR4XoYQC71LbEI7jsig== + dependencies: + "@azure/abort-controller" "^1.0.0" + tslib "^2.2.0" + "@azure/logger@^1.0.0": version "1.0.3" resolved "https://registry.yarnpkg.com/@azure/logger/-/logger-1.0.3.tgz#6e36704aa51be7d4a1bae24731ea580836293c96" @@ -55,71 +80,105 @@ dependencies: tslib "^2.2.0" +"@azure/opentelemetry-instrumentation-azure-sdk@^1.0.0-beta.5": + version "1.0.0-beta.5" + resolved "https://registry.yarnpkg.com/@azure/opentelemetry-instrumentation-azure-sdk/-/opentelemetry-instrumentation-azure-sdk-1.0.0-beta.5.tgz#78809e6c005d08450701e5d37f087f6fce2f86eb" + integrity sha512-fsUarKQDvjhmBO4nIfaZkfNSApm1hZBzcvpNbSrXdcUBxu7lRvKsV5DnwszX7cnhLyVOW9yl1uigtRQ1yDANjA== + dependencies: + "@azure/core-tracing" "^1.0.0" + "@azure/logger" "^1.0.0" + "@opentelemetry/api" "^1.4.1" + "@opentelemetry/core" "^1.15.2" + "@opentelemetry/instrumentation" "^0.41.2" + tslib "^2.2.0" + "@joaomoreno/unique-names-generator@^5.1.0": version "5.1.0" resolved "https://registry.yarnpkg.com/@joaomoreno/unique-names-generator/-/unique-names-generator-5.1.0.tgz#d577d425aed794c44c0e8863cddd5dea349f74f3" integrity sha512-KEVThTpUIKPb7dBKJ9mJ3WYnD1mJZZsEinCSp9CVEPlWbDagurFv1RKRjvvujrLfJzsGc0HkBHS9W8Bughao4A== -"@microsoft/1ds-core-js@3.2.8", "@microsoft/1ds-core-js@^3.2.8": - version "3.2.8" - resolved "https://registry.yarnpkg.com/@microsoft/1ds-core-js/-/1ds-core-js-3.2.8.tgz#1b6b7d9bb858238c818ccf4e4b58ece7aeae5760" - integrity sha512-9o9SUAamJiTXIYwpkQDuueYt83uZfXp8zp8YFix1IwVPwC9RmE36T2CX9gXOeq1nDckOuOduYpA8qHvdh5BGfQ== +"@microsoft/1ds-core-js@3.2.13", "@microsoft/1ds-core-js@^3.2.13": + version "3.2.13" + resolved "https://registry.yarnpkg.com/@microsoft/1ds-core-js/-/1ds-core-js-3.2.13.tgz#0c105ed75091bae3f1555c0334704fa9911c58fb" + integrity sha512-CluYTRWcEk0ObG5EWFNWhs87e2qchJUn0p2D21ZUa3PWojPZfPSBs4//WIE0MYV8Qg1Hdif2ZTwlM7TbYUjfAg== dependencies: - "@microsoft/applicationinsights-core-js" "2.8.9" + "@microsoft/applicationinsights-core-js" "2.8.15" "@microsoft/applicationinsights-shims" "^2.0.2" "@microsoft/dynamicproto-js" "^1.1.7" -"@microsoft/1ds-post-js@^3.2.8": - version "3.2.8" - resolved "https://registry.yarnpkg.com/@microsoft/1ds-post-js/-/1ds-post-js-3.2.8.tgz#46793842cca161bf7a2a5b6053c349f429e55110" - integrity sha512-SjlRoNcXcXBH6WQD/5SkkaCHIVqldH3gDu+bI7YagrOVJ5APxwT1Duw9gm3L1FjFa9S2i81fvJ3EVSKpp9wULA== +"@microsoft/1ds-post-js@^3.2.13": + version "3.2.13" + resolved "https://registry.yarnpkg.com/@microsoft/1ds-post-js/-/1ds-post-js-3.2.13.tgz#560aacac8a92fdbb79e8c2ebcb293d56e19f51aa" + integrity sha512-HgS574fdD19Bo2vPguyznL4eDw7Pcm1cVNpvbvBLWiW3x4e1FCQ3VMXChWnAxCae8Hb0XqlA2sz332ZobBavTA== dependencies: - "@microsoft/1ds-core-js" "3.2.8" + "@microsoft/1ds-core-js" "3.2.13" "@microsoft/applicationinsights-shims" "^2.0.2" "@microsoft/dynamicproto-js" "^1.1.7" -"@microsoft/applicationinsights-channel-js@2.8.9": - version "2.8.9" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-channel-js/-/applicationinsights-channel-js-2.8.9.tgz#840656f3c716de8b3eb0a98c122aa1b92bb8ebfb" - integrity sha512-fMBsAEB7pWtPn43y72q9Xy5E5y55r6gMuDQqRRccccVoQDPXyS57VCj5IdATblctru0C6A8XpL2vRyNmEsu0Vg== +"@microsoft/applicationinsights-channel-js@3.0.2": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-channel-js/-/applicationinsights-channel-js-3.0.2.tgz#be49fbf74831c7b8c97950027c5052ea99d2a8a5" + integrity sha512-jDBNKbCHsJgmpv0CKNhJ/uN9ZphvfGdb93Svk+R4LjO8L3apNNMbDDPxBvXXi0uigRmA1TBcmyBG4IRKjabGhw== dependencies: - "@microsoft/applicationinsights-common" "2.8.9" - "@microsoft/applicationinsights-core-js" "2.8.9" - "@microsoft/applicationinsights-shims" "2.0.2" - "@microsoft/dynamicproto-js" "^1.1.7" + "@microsoft/applicationinsights-common" "3.0.2" + "@microsoft/applicationinsights-core-js" "3.0.2" + "@microsoft/applicationinsights-shims" "3.0.1" + "@microsoft/dynamicproto-js" "^2.0.2" + "@nevware21/ts-async" ">= 0.2.4 < 2.x" + "@nevware21/ts-utils" ">= 0.9.5 < 2.x" -"@microsoft/applicationinsights-common@2.8.9": - version "2.8.9" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-common/-/applicationinsights-common-2.8.9.tgz#a75e4a3143a7fd797687830c0ddd2069fd900827" - integrity sha512-mObn1moElyxZaGIRF/IU3cOaeKMgxghXnYEoHNUCA2e+rNwBIgxjyKkblFIpmGuHf4X7Oz3o3yBWpaC6AoMpig== +"@microsoft/applicationinsights-common@3.0.2": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-common/-/applicationinsights-common-3.0.2.tgz#37670bb07f4858ed41ff9759119e0759007d6e05" + integrity sha512-y+WXWop+OVim954Cu1uyYMnNx6PWO8okHpZIQi/1YSqtqaYdtJVPv4P0AVzwJdohxzVfgzKvqj9nec/VWqE2Zg== dependencies: - "@microsoft/applicationinsights-core-js" "2.8.9" - "@microsoft/applicationinsights-shims" "2.0.2" - "@microsoft/dynamicproto-js" "^1.1.7" + "@microsoft/applicationinsights-core-js" "3.0.2" + "@microsoft/applicationinsights-shims" "3.0.1" + "@microsoft/dynamicproto-js" "^2.0.2" + "@nevware21/ts-utils" ">= 0.9.5 < 2.x" -"@microsoft/applicationinsights-core-js@2.8.9": - version "2.8.9" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-2.8.9.tgz#0e5d207acfae6986a6fc97249eeb6117e523bf1b" - integrity sha512-HRuIuZ6aOWezcg/G5VyFDDWGL8hDNe/ljPP01J7ImH2kRPEgbtcfPSUMjkamGMefgdq81GZsSoC/NNGTP4pp2w== +"@microsoft/applicationinsights-core-js@2.8.15": + version "2.8.15" + resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-2.8.15.tgz#8fa466474260e01967fe649f14dd9e5ff91dcdc8" + integrity sha512-yYAs9MyjGr2YijQdUSN9mVgT1ijI1FPMgcffpaPmYbHAVbQmF7bXudrBWHxmLzJlwl5rfep+Zgjli2e67lwUqQ== dependencies: "@microsoft/applicationinsights-shims" "2.0.2" - "@microsoft/dynamicproto-js" "^1.1.7" + "@microsoft/dynamicproto-js" "^1.1.9" + +"@microsoft/applicationinsights-core-js@3.0.2": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-3.0.2.tgz#108e20df8c162bec92b1f66f9de2530a25d9f51a" + integrity sha512-WQhVhzlRlLDrQzn3OShCW/pL3BW5WC57t0oywSknX3q7lMzI3jDg7Ihh0iuIcNTzGCTbDkuqr4d6IjEDWIMtJQ== + dependencies: + "@microsoft/applicationinsights-shims" "3.0.1" + "@microsoft/dynamicproto-js" "^2.0.2" + "@nevware21/ts-async" ">= 0.2.4 < 2.x" + "@nevware21/ts-utils" ">= 0.9.5 < 2.x" "@microsoft/applicationinsights-shims@2.0.2", "@microsoft/applicationinsights-shims@^2.0.2": version "2.0.2" resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-shims/-/applicationinsights-shims-2.0.2.tgz#92b36a09375e2d9cb2b4203383b05772be837085" integrity sha512-PoHEgsnmcqruLNHZ/amACqdJ6YYQpED0KSRe6J7gIJTtpZC1FfFU9b1fmDKDKtFoUSrPzEh1qzO3kmRZP0betg== -"@microsoft/applicationinsights-web-basic@^2.8.9": - version "2.8.9" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-web-basic/-/applicationinsights-web-basic-2.8.9.tgz#eed2f3d1e19069962ed2155915c1656e6936e1d5" - integrity sha512-CH0J8JFOy7MjK8JO4pXXU+EML+Ilix+94PMZTX5EJlBU1in+mrik74/8qSg3UC4ekPi12KwrXaHCQSVC3WseXQ== +"@microsoft/applicationinsights-shims@3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-shims/-/applicationinsights-shims-3.0.1.tgz#3865b73ace8405b9c4618cc5c571f2fe3876f06f" + integrity sha512-DKwboF47H1nb33rSUfjqI6ryX29v+2QWcTrRvcQDA32AZr5Ilkr7whOOSsD1aBzwqX0RJEIP1Z81jfE3NBm/Lg== dependencies: - "@microsoft/applicationinsights-channel-js" "2.8.9" - "@microsoft/applicationinsights-common" "2.8.9" - "@microsoft/applicationinsights-core-js" "2.8.9" - "@microsoft/applicationinsights-shims" "2.0.2" - "@microsoft/dynamicproto-js" "^1.1.7" + "@nevware21/ts-utils" ">= 0.9.4 < 2.x" + +"@microsoft/applicationinsights-web-basic@^3.0.2": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-web-basic/-/applicationinsights-web-basic-3.0.2.tgz#f777a4d24b79dde3ae396d3b819e1fce06b7240a" + integrity sha512-6Lq0DE/pZp9RvSV+weGbcxN1NDmfczj6gNPhvZKV2YSQ3RK0LZE3+wjTWLXfuStq8a+nCBdsRpWk8tOKgsoxcg== + dependencies: + "@microsoft/applicationinsights-channel-js" "3.0.2" + "@microsoft/applicationinsights-common" "3.0.2" + "@microsoft/applicationinsights-core-js" "3.0.2" + "@microsoft/applicationinsights-shims" "3.0.1" + "@microsoft/dynamicproto-js" "^2.0.2" + "@nevware21/ts-async" ">= 0.2.4 < 2.x" + "@nevware21/ts-utils" ">= 0.9.5 < 2.x" "@microsoft/applicationinsights-web-snippet@^1.0.1": version "1.0.1" @@ -131,39 +190,74 @@ resolved "https://registry.yarnpkg.com/@microsoft/dynamicproto-js/-/dynamicproto-js-1.1.7.tgz#ede48dd3f85af14ee369c805e5ed5b84222b9fe2" integrity sha512-SK3D3aVt+5vOOccKPnGaJWB5gQ8FuKfjboUJHedMP7gu54HqSCXX5iFXhktGD8nfJb0Go30eDvs/UDoTnR2kOA== -"@opentelemetry/api@^1.0.4": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.2.0.tgz#89ef99401cde6208cff98760b67663726ef26686" - integrity sha512-0nBr+VZNKm9tvNDZFstI3Pq1fCTEDK5OZTnVKNvBNAKgd0yIvmwsP4m61rEv7ZP+tOUjWJhROpxK5MsnlF911g== +"@microsoft/dynamicproto-js@^1.1.9": + version "1.1.9" + resolved "https://registry.yarnpkg.com/@microsoft/dynamicproto-js/-/dynamicproto-js-1.1.9.tgz#7437db7aa061162ee94e4131b69a62b8dad5dea6" + integrity sha512-n1VPsljTSkthsAFYdiWfC+DKzK2WwcRp83Y1YAqdX552BstvsDjft9YXppjUzp11BPsapDoO1LDgrDB0XVsfNQ== -"@opentelemetry/core@1.7.0", "@opentelemetry/core@^1.0.1": - version "1.7.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-1.7.0.tgz#83bdd1b7a4ceafcdffd6590420657caec5f7b34c" - integrity sha512-AVqAi5uc8DrKJBimCTFUT4iFI+5eXpo4sYmGbQ0CypG0piOTHE2g9c5aSoTGYXu3CzOmJZf7pT6Xh+nwm5d6yQ== +"@microsoft/dynamicproto-js@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@microsoft/dynamicproto-js/-/dynamicproto-js-2.0.2.tgz#e57fbec2e7067d48b7e8e1e1c1d354028ef718a6" + integrity sha512-MB8trWaFREpmb037k/d0bB7T2BP7Ai24w1e1tbz3ASLB0/lwphsq3Nq8S9I5AsI5vs4zAQT+SB5nC5/dLYTiOg== dependencies: - "@opentelemetry/semantic-conventions" "1.7.0" + "@nevware21/ts-utils" ">= 0.9.4 < 2.x" -"@opentelemetry/resources@1.7.0": - version "1.7.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/resources/-/resources-1.7.0.tgz#90ccd3a6a86b4dfba4e833e73944bd64958d78c5" - integrity sha512-u1M0yZotkjyKx8dj+46Sg5thwtOTBmtRieNXqdCRiWUp6SfFiIP0bI+1XK3LhuXqXkBXA1awJZaTqKduNMStRg== +"@nevware21/ts-async@>= 0.2.4 < 2.x": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@nevware21/ts-async/-/ts-async-0.3.0.tgz#a8b97ba01065fc930de9a3f4dd4a05e862becc6c" + integrity sha512-ZUcgUH12LN/F6nzN0cYd0F/rJaMLmXr0EHVTyYfaYmK55bdwE4338uue4UiVoRqHVqNW4KDUrJc49iGogHKeWA== dependencies: - "@opentelemetry/core" "1.7.0" - "@opentelemetry/semantic-conventions" "1.7.0" + "@nevware21/ts-utils" ">= 0.10.0 < 2.x" -"@opentelemetry/sdk-trace-base@^1.0.1": - version "1.7.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.7.0.tgz#b498424e0c6340a9d80de63fd408c5c2130a60a5" - integrity sha512-Iz84C+FVOskmauh9FNnj4+VrA+hG5o+tkMzXuoesvSfunVSioXib0syVFeNXwOm4+M5GdWCuW632LVjqEXStIg== +"@nevware21/ts-utils@>= 0.10.0 < 2.x", "@nevware21/ts-utils@>= 0.9.4 < 2.x", "@nevware21/ts-utils@>= 0.9.5 < 2.x": + version "0.10.1" + resolved "https://registry.yarnpkg.com/@nevware21/ts-utils/-/ts-utils-0.10.1.tgz#aa65abc71eba06749a396598f22263d26f796ac7" + integrity sha512-pMny25NnF2/MJwdqC3Iyjm2pGIXNxni4AROpcqDeWa+td9JMUY4bUS9uU9XW+BoBRqTLUL+WURF9SOd/6OQzRg== + +"@opentelemetry/api@^1.4.1": + version "1.4.1" + resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.4.1.tgz#ff22eb2e5d476fbc2450a196e40dd243cc20c28f" + integrity sha512-O2yRJce1GOc6PAy3QxFM4NzFiWzvScDC1/5ihYBL6BUEVdq0XMWN01sppE+H6bBXbaFYipjwFLEWLg5PaSOThA== + +"@opentelemetry/core@1.15.2", "@opentelemetry/core@^1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-1.15.2.tgz#5b170bf223a2333884bbc2d29d95812cdbda7c9f" + integrity sha512-+gBv15ta96WqkHZaPpcDHiaz0utiiHZVfm2YOYSqFGrUaJpPkMoSuLBB58YFQGi6Rsb9EHos84X6X5+9JspmLw== dependencies: - "@opentelemetry/core" "1.7.0" - "@opentelemetry/resources" "1.7.0" - "@opentelemetry/semantic-conventions" "1.7.0" + "@opentelemetry/semantic-conventions" "1.15.2" -"@opentelemetry/semantic-conventions@1.7.0", "@opentelemetry/semantic-conventions@^1.0.1": - version "1.7.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.7.0.tgz#af80a1ef7cf110ea3a68242acd95648991bcd763" - integrity sha512-FGBx/Qd09lMaqQcogCHyYrFEpTx4cAjeS+48lMIR12z7LdH+zofGDVQSubN59nL6IpubfKqTeIDu9rNO28iHVA== +"@opentelemetry/instrumentation@^0.41.2": + version "0.41.2" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation/-/instrumentation-0.41.2.tgz#cae11fa64485dcf03dae331f35b315b64bc6189f" + integrity sha512-rxU72E0pKNH6ae2w5+xgVYZLzc5mlxAbGzF4shxMVK8YC2QQsfN38B2GPbj0jvrKWWNUElfclQ+YTykkNg/grw== + dependencies: + "@types/shimmer" "^1.0.2" + import-in-the-middle "1.4.2" + require-in-the-middle "^7.1.1" + semver "^7.5.1" + shimmer "^1.2.1" + +"@opentelemetry/resources@1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@opentelemetry/resources/-/resources-1.15.2.tgz#0c9e26cb65652a1402834a3c030cce6028d6dd9d" + integrity sha512-xmMRLenT9CXmm5HMbzpZ1hWhaUowQf8UB4jMjFlAxx1QzQcsD3KFNAVX/CAWzFPtllTyTplrA4JrQ7sCH3qmYw== + dependencies: + "@opentelemetry/core" "1.15.2" + "@opentelemetry/semantic-conventions" "1.15.2" + +"@opentelemetry/sdk-trace-base@^1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.15.2.tgz#4821f94033c55a6c8bbd35ae387b715b6108517a" + integrity sha512-BEaxGZbWtvnSPchV98qqqqa96AOcb41pjgvhfzDij10tkBhIu9m0Jd6tZ1tJB5ZHfHbTffqYVYE0AOGobec/EQ== + dependencies: + "@opentelemetry/core" "1.15.2" + "@opentelemetry/resources" "1.15.2" + "@opentelemetry/semantic-conventions" "1.15.2" + +"@opentelemetry/semantic-conventions@1.15.2", "@opentelemetry/semantic-conventions@^1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.15.2.tgz#3bafb5de3e20e841dff6cb3c66f4d6e9694c4241" + integrity sha512-CjbOKwk2s+3xPIMcd5UNYQzsf+v94RczbdNix9/kQh38WiQkM90sUOi3if8eyHFgiBjBjhwXrA7W3ydiSQP9mw== "@tokenizer/token@^0.3.0": version "0.3.0" @@ -202,26 +296,41 @@ resolved "https://registry.yarnpkg.com/@types/picomatch/-/picomatch-2.3.0.tgz#75db5e75a713c5a83d5b76780c3da84a82806003" integrity sha512-O397rnSS9iQI4OirieAtsDqvCj4+3eY1J+EPdNTKuHuRWIfUoGyzX294o8C4KJYaLqgSrd2o60c5EqCU8Zv02g== +"@types/shimmer@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@types/shimmer/-/shimmer-1.0.2.tgz#93eb2c243c351f3f17d5c580c7467ae5d686b65f" + integrity sha512-dKkr1bTxbEsFlh2ARpKzcaAmsYixqt9UyCdoEZk8rHyE4iQYcDCyvSjDSf7JUWJHlJiTtbIoQjxKh6ViywqDAg== + "@types/which@3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@types/which/-/which-3.0.0.tgz#849afdd9fdcb0b67339b9cfc80fa6ea4e0253fc5" integrity sha512-ASCxdbsrwNfSMXALlC3Decif9rwDMu+80KGp5zI2RLRotfMsTv7fHL8W8VDp24wymzDyIFudhUeSCugrgRFfHQ== -"@vscode/extension-telemetry@0.7.5": - version "0.7.5" - resolved "https://registry.yarnpkg.com/@vscode/extension-telemetry/-/extension-telemetry-0.7.5.tgz#bf965731816e08c3f146f96d901ec67954fc913b" - integrity sha512-fJ5y3TcpqqkFYHneabYaoB4XAhDdVflVm+TDKshw9VOs77jkgNS4UA7LNXrWeO0eDne3Sh3JgURf+xzc1rk69w== +"@vscode/extension-telemetry@^0.8.4": + version "0.8.4" + resolved "https://registry.yarnpkg.com/@vscode/extension-telemetry/-/extension-telemetry-0.8.4.tgz#c078c6f55df1c9e0592de3b4ce0f685dd345bfe7" + integrity sha512-UqM9+KZDDK3MyoHTsg6XNM+XO6pweQxzCpqJz33BoBEYAGsbBviRYcVpJglgay2oReuDD2pOI1Nio3BKNDLhWA== dependencies: - "@microsoft/1ds-core-js" "^3.2.8" - "@microsoft/1ds-post-js" "^3.2.8" - "@microsoft/applicationinsights-web-basic" "^2.8.9" - applicationinsights "2.4.1" + "@microsoft/1ds-core-js" "^3.2.13" + "@microsoft/1ds-post-js" "^3.2.13" + "@microsoft/applicationinsights-web-basic" "^3.0.2" + applicationinsights "^2.7.1" "@vscode/iconv-lite-umd@0.7.0": version "0.7.0" resolved "https://registry.yarnpkg.com/@vscode/iconv-lite-umd/-/iconv-lite-umd-0.7.0.tgz#d2f1e0664ee6036408f9743fee264ea0699b0e48" integrity sha512-bRRFxLfg5dtAyl5XyiVWz/ZBPahpOpPrNYnnHpOpUZvam4tKH35wdhP4Kj6PbM0+KdliOsPzbGWpkxcdpNB/sg== +acorn-import-assertions@^1.9.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz#507276249d684797c84e0734ef84860334cfb1ac" + integrity sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA== + +acorn@^8.8.2: + version "8.10.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5" + integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw== + agent-base@6: version "6.0.2" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" @@ -229,22 +338,24 @@ agent-base@6: dependencies: debug "4" -applicationinsights@2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/applicationinsights/-/applicationinsights-2.4.1.tgz#4de4c4dd3c7c4a44445cfbf3d15808fc0dcc423d" - integrity sha512-0n0Ikd0gzSm460xm+M0UTWIwXrhrH/0bqfZatcJjYObWyefxfAxapGEyNnSGd1Tg90neHz+Yhf+Ff/zgvPiQYA== +applicationinsights@^2.7.1: + version "2.7.3" + resolved "https://registry.yarnpkg.com/applicationinsights/-/applicationinsights-2.7.3.tgz#8781454d29c0b14c9773f2e892b4cf5e7468ffa5" + integrity sha512-JY8+kTEkjbA+kAVNWDtpfW2lqsrDALfDXuxOs74KLPu2y13fy/9WB52V4LfYVTVcW1/jYOXjTxNS2gPZIDh1iw== dependencies: - "@azure/core-auth" "^1.4.0" - "@azure/core-rest-pipeline" "^1.10.0" + "@azure/core-auth" "^1.5.0" + "@azure/core-rest-pipeline" "1.10.1" + "@azure/core-util" "1.2.0" + "@azure/opentelemetry-instrumentation-azure-sdk" "^1.0.0-beta.5" "@microsoft/applicationinsights-web-snippet" "^1.0.1" - "@opentelemetry/api" "^1.0.4" - "@opentelemetry/core" "^1.0.1" - "@opentelemetry/sdk-trace-base" "^1.0.1" - "@opentelemetry/semantic-conventions" "^1.0.1" + "@opentelemetry/api" "^1.4.1" + "@opentelemetry/core" "^1.15.2" + "@opentelemetry/sdk-trace-base" "^1.15.2" + "@opentelemetry/semantic-conventions" "^1.15.2" cls-hooked "^4.2.2" continuation-local-storage "^3.2.1" - diagnostic-channel "1.1.0" - diagnostic-channel-publishers "1.0.5" + diagnostic-channel "1.1.1" + diagnostic-channel-publishers "1.0.7" async-hook-jl@^1.7.6: version "1.7.6" @@ -271,6 +382,11 @@ byline@^5.0.0: resolved "https://registry.yarnpkg.com/byline/-/byline-5.0.0.tgz#741c5216468eadc457b03410118ad77de8c1ddb1" integrity sha1-dBxSFkaOrcRXsDQQEYrXfejB3bE= +cjs-module-lexer@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz#6c370ab19f8a3394e318fe682686ec0ac684d107" + integrity sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ== + cls-hooked@^4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/cls-hooked/-/cls-hooked-4.2.2.tgz#ad2e9a4092680cdaffeb2d3551da0e225eae1908" @@ -295,7 +411,7 @@ continuation-local-storage@^3.2.1: async-listener "^0.6.0" emitter-listener "^1.1.1" -debug@4: +debug@4, debug@^4.1.1: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== @@ -307,17 +423,17 @@ delayed-stream@~1.0.0: resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== -diagnostic-channel-publishers@1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/diagnostic-channel-publishers/-/diagnostic-channel-publishers-1.0.5.tgz#df8c317086c50f5727fdfb5d2fce214d2e4130ae" - integrity sha512-dJwUS0915pkjjimPJVDnS/QQHsH0aOYhnZsLJdnZIMOrB+csj8RnZhWTuwnm8R5v3Z7OZs+ksv5luC14DGB7eg== +diagnostic-channel-publishers@1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/diagnostic-channel-publishers/-/diagnostic-channel-publishers-1.0.7.tgz#9b7f8d5ee1295481aee19c827d917e96fedf2c4a" + integrity sha512-SEECbY5AiVt6DfLkhkaHNeshg1CogdLLANA8xlG/TKvS+XUgvIKl7VspJGYiEdL5OUyzMVnr7o0AwB7f+/Mjtg== -diagnostic-channel@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/diagnostic-channel/-/diagnostic-channel-1.1.0.tgz#6985e9dfedfbc072d91dc4388477e4087147756e" - integrity sha512-fwujyMe1gj6rk6dYi9hMZm0c8Mz8NDMVl2LB4iaYh3+LIAThZC8RKFGXWG0IML2OxAit/ZFRgZhMkhQ3d/bobQ== +diagnostic-channel@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/diagnostic-channel/-/diagnostic-channel-1.1.1.tgz#44b60972de9ee055c16216535b0e9db3f6a0efd0" + integrity sha512-r2HV5qFkUICyoaKlBEpLKHjxMXATUf/l+h8UZPGBHGLy4DDiY2sOLcIctax4eRnTw5wH2jTMExLntGPJ8eOJxw== dependencies: - semver "^5.3.0" + semver "^7.5.3" emitter-listener@^1.0.1, emitter-listener@^1.1.1: version "1.1.2" @@ -344,6 +460,18 @@ form-data@^4.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + http-proxy-agent@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz#5129800203520d434f142bc78ff3c170800f2b43" @@ -366,11 +494,28 @@ ieee754@^1.2.1: resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== +import-in-the-middle@1.4.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/import-in-the-middle/-/import-in-the-middle-1.4.2.tgz#2a266676e3495e72c04bbaa5ec14756ba168391b" + integrity sha512-9WOz1Yh/cvO/p69sxRmhyQwrIGGSp7EIdcb+fFNVi7CzQGQB8U1/1XrKVSbEd/GNOAeM0peJtmi7+qphe7NvAw== + dependencies: + acorn "^8.8.2" + acorn-import-assertions "^1.9.0" + cjs-module-lexer "^1.2.2" + module-details-from-path "^1.0.3" + inherits@^2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== +is-core-module@^2.13.0: + version "2.13.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.0.tgz#bb52aa6e2cbd49a30c2ba68c42bf3435ba6072db" + integrity sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ== + dependencies: + has "^1.0.3" + isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" @@ -381,6 +526,13 @@ jschardet@3.0.0: resolved "https://registry.yarnpkg.com/jschardet/-/jschardet-3.0.0.tgz#898d2332e45ebabbdb6bf2feece9feea9a99e882" integrity sha512-lJH6tJ77V8Nzd5QWRkFYCLc13a3vADkh3r/Fi8HupZGWk2OVVDfnZP8V/VgQgZ+lzW0kG2UGb5hFgt3V3ndotQ== +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + mime-db@1.52.0: version "1.52.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" @@ -393,11 +545,21 @@ mime-types@^2.1.12: dependencies: mime-db "1.52.0" +module-details-from-path@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/module-details-from-path/-/module-details-from-path-1.0.3.tgz#114c949673e2a8a35e9d35788527aa37b679da2b" + integrity sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A== + ms@2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + peek-readable@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/peek-readable/-/peek-readable-4.1.0.tgz#4ece1111bf5c2ad8867c314c81356847e8a62e72" @@ -424,6 +586,24 @@ readable-web-to-node-stream@^3.0.0: dependencies: readable-stream "^3.6.0" +require-in-the-middle@^7.1.1: + version "7.2.0" + resolved "https://registry.yarnpkg.com/require-in-the-middle/-/require-in-the-middle-7.2.0.tgz#b539de8f00955444dc8aed95e17c69b0a4f10fcf" + integrity sha512-3TLx5TGyAY6AOqLBoXmHkNql0HIf2RGbuMgCDT2WO/uGVAPJs6h7Kl+bN6TIZGd9bWhWPwnDnTHGtW8Iu77sdw== + dependencies: + debug "^4.1.1" + module-details-from-path "^1.0.3" + resolve "^1.22.1" + +resolve@^1.22.1: + version "1.22.4" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.4.tgz#1dc40df46554cdaf8948a486a10f6ba1e2026c34" + integrity sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg== + dependencies: + is-core-module "^2.13.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" @@ -434,7 +614,14 @@ semver@^5.3.0, semver@^5.4.1: resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== -shimmer@^1.1.0, shimmer@^1.2.0: +semver@^7.5.1, semver@^7.5.3: + version "7.5.4" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" + integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== + dependencies: + lru-cache "^6.0.0" + +shimmer@^1.1.0, shimmer@^1.2.0, shimmer@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/shimmer/-/shimmer-1.2.1.tgz#610859f7de327b587efebf501fb43117f9aff337" integrity sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw== @@ -459,6 +646,11 @@ strtok3@^6.2.4: "@tokenizer/token" "^0.3.0" peek-readable "^4.1.0" +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + token-types@^4.1.1: version "4.2.0" resolved "https://registry.yarnpkg.com/token-types/-/token-types-4.2.0.tgz#b66bc3d67420c6873222a424eee64a744f4c2f13" @@ -493,3 +685,8 @@ which@3.0.1: integrity sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg== dependencies: isexe "^2.0.0" + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== diff --git a/extensions/github-authentication/package.json b/extensions/github-authentication/package.json index f5e3c95e6dd..4855716e08e 100644 --- a/extensions/github-authentication/package.json +++ b/extensions/github-authentication/package.json @@ -60,7 +60,7 @@ }, "dependencies": { "node-fetch": "2.6.7", - "@vscode/extension-telemetry": "0.7.5", + "@vscode/extension-telemetry": "^0.8.4", "vscode-tas-client": "^0.1.47" }, "devDependencies": { diff --git a/extensions/github-authentication/yarn.lock b/extensions/github-authentication/yarn.lock index 858f60ddaff..da5f5631576 100644 --- a/extensions/github-authentication/yarn.lock +++ b/extensions/github-authentication/yarn.lock @@ -17,7 +17,16 @@ "@azure/abort-controller" "^1.0.0" tslib "^2.2.0" -"@azure/core-rest-pipeline@^1.10.0": +"@azure/core-auth@^1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@azure/core-auth/-/core-auth-1.5.0.tgz#a41848c5c31cb3b7c84c409885267d55a2c92e44" + integrity sha512-udzoBuYG1VBoHVohDTrvKjyzel34zt77Bhp7dQntVGGD0ehVq48owENbBG8fIgkHRNUBQH5k1r0hpoMu5L8+kw== + dependencies: + "@azure/abort-controller" "^1.0.0" + "@azure/core-util" "^1.1.0" + tslib "^2.2.0" + +"@azure/core-rest-pipeline@1.10.1": version "1.10.1" resolved "https://registry.yarnpkg.com/@azure/core-rest-pipeline/-/core-rest-pipeline-1.10.1.tgz#348290847ca31b9eecf9cf5de7519aaccdd30968" integrity sha512-Kji9k6TOFRDB5ZMTw8qUf2IJ+CeJtsuMdAHox9eqpTf1cefiNMpzrfnF6sINEBZJsaVaWgQ0o48B6kcUH68niA== @@ -33,13 +42,21 @@ tslib "^2.2.0" uuid "^8.3.0" -"@azure/core-tracing@^1.0.1": +"@azure/core-tracing@^1.0.0", "@azure/core-tracing@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@azure/core-tracing/-/core-tracing-1.0.1.tgz#352a38cbea438c4a83c86b314f48017d70ba9503" integrity sha512-I5CGMoLtX+pI17ZdiFJZgxMJApsK6jjfm85hpgp3oazCdq5Wxgh4wMr7ge/TTWW1B5WBuvIOI1fMU/FrOAMKrw== dependencies: tslib "^2.2.0" +"@azure/core-util@1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@azure/core-util/-/core-util-1.2.0.tgz#3499deba1fc36dda6f1912b791809b6f15d4a392" + integrity sha512-ffGIw+Qs8bNKNLxz5UPkz4/VBM/EZY07mPve1ZYFqYUdPwFqRj0RPk0U7LZMOfT7GCck9YjuT1Rfp1PApNl1ng== + dependencies: + "@azure/abort-controller" "^1.0.0" + tslib "^2.2.0" + "@azure/core-util@^1.0.0": version "1.1.1" resolved "https://registry.yarnpkg.com/@azure/core-util/-/core-util-1.1.1.tgz#8f87b3dd468795df0f0849d9f096c3e7b29452c1" @@ -48,6 +65,14 @@ "@azure/abort-controller" "^1.0.0" tslib "^2.2.0" +"@azure/core-util@^1.1.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@azure/core-util/-/core-util-1.4.0.tgz#c120a56b3e48a9e4d20619a0b00268ae9de891c7" + integrity sha512-eGAyJpm3skVQoLiRqm/xPa+SXi/NPDdSHMxbRAz2lSprd+Zs+qrpQGQQ2VQ3Nttu+nSZR4XoYQC71LbEI7jsig== + dependencies: + "@azure/abort-controller" "^1.0.0" + tslib "^2.2.0" + "@azure/logger@^1.0.0": version "1.0.3" resolved "https://registry.yarnpkg.com/@azure/logger/-/logger-1.0.3.tgz#6e36704aa51be7d4a1bae24731ea580836293c96" @@ -55,66 +80,100 @@ dependencies: tslib "^2.2.0" -"@microsoft/1ds-core-js@3.2.8", "@microsoft/1ds-core-js@^3.2.8": - version "3.2.8" - resolved "https://registry.yarnpkg.com/@microsoft/1ds-core-js/-/1ds-core-js-3.2.8.tgz#1b6b7d9bb858238c818ccf4e4b58ece7aeae5760" - integrity sha512-9o9SUAamJiTXIYwpkQDuueYt83uZfXp8zp8YFix1IwVPwC9RmE36T2CX9gXOeq1nDckOuOduYpA8qHvdh5BGfQ== +"@azure/opentelemetry-instrumentation-azure-sdk@^1.0.0-beta.5": + version "1.0.0-beta.5" + resolved "https://registry.yarnpkg.com/@azure/opentelemetry-instrumentation-azure-sdk/-/opentelemetry-instrumentation-azure-sdk-1.0.0-beta.5.tgz#78809e6c005d08450701e5d37f087f6fce2f86eb" + integrity sha512-fsUarKQDvjhmBO4nIfaZkfNSApm1hZBzcvpNbSrXdcUBxu7lRvKsV5DnwszX7cnhLyVOW9yl1uigtRQ1yDANjA== dependencies: - "@microsoft/applicationinsights-core-js" "2.8.9" + "@azure/core-tracing" "^1.0.0" + "@azure/logger" "^1.0.0" + "@opentelemetry/api" "^1.4.1" + "@opentelemetry/core" "^1.15.2" + "@opentelemetry/instrumentation" "^0.41.2" + tslib "^2.2.0" + +"@microsoft/1ds-core-js@3.2.13", "@microsoft/1ds-core-js@^3.2.13": + version "3.2.13" + resolved "https://registry.yarnpkg.com/@microsoft/1ds-core-js/-/1ds-core-js-3.2.13.tgz#0c105ed75091bae3f1555c0334704fa9911c58fb" + integrity sha512-CluYTRWcEk0ObG5EWFNWhs87e2qchJUn0p2D21ZUa3PWojPZfPSBs4//WIE0MYV8Qg1Hdif2ZTwlM7TbYUjfAg== + dependencies: + "@microsoft/applicationinsights-core-js" "2.8.15" "@microsoft/applicationinsights-shims" "^2.0.2" "@microsoft/dynamicproto-js" "^1.1.7" -"@microsoft/1ds-post-js@^3.2.8": - version "3.2.8" - resolved "https://registry.yarnpkg.com/@microsoft/1ds-post-js/-/1ds-post-js-3.2.8.tgz#46793842cca161bf7a2a5b6053c349f429e55110" - integrity sha512-SjlRoNcXcXBH6WQD/5SkkaCHIVqldH3gDu+bI7YagrOVJ5APxwT1Duw9gm3L1FjFa9S2i81fvJ3EVSKpp9wULA== +"@microsoft/1ds-post-js@^3.2.13": + version "3.2.13" + resolved "https://registry.yarnpkg.com/@microsoft/1ds-post-js/-/1ds-post-js-3.2.13.tgz#560aacac8a92fdbb79e8c2ebcb293d56e19f51aa" + integrity sha512-HgS574fdD19Bo2vPguyznL4eDw7Pcm1cVNpvbvBLWiW3x4e1FCQ3VMXChWnAxCae8Hb0XqlA2sz332ZobBavTA== dependencies: - "@microsoft/1ds-core-js" "3.2.8" + "@microsoft/1ds-core-js" "3.2.13" "@microsoft/applicationinsights-shims" "^2.0.2" "@microsoft/dynamicproto-js" "^1.1.7" -"@microsoft/applicationinsights-channel-js@2.8.9": - version "2.8.9" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-channel-js/-/applicationinsights-channel-js-2.8.9.tgz#840656f3c716de8b3eb0a98c122aa1b92bb8ebfb" - integrity sha512-fMBsAEB7pWtPn43y72q9Xy5E5y55r6gMuDQqRRccccVoQDPXyS57VCj5IdATblctru0C6A8XpL2vRyNmEsu0Vg== +"@microsoft/applicationinsights-channel-js@3.0.2": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-channel-js/-/applicationinsights-channel-js-3.0.2.tgz#be49fbf74831c7b8c97950027c5052ea99d2a8a5" + integrity sha512-jDBNKbCHsJgmpv0CKNhJ/uN9ZphvfGdb93Svk+R4LjO8L3apNNMbDDPxBvXXi0uigRmA1TBcmyBG4IRKjabGhw== dependencies: - "@microsoft/applicationinsights-common" "2.8.9" - "@microsoft/applicationinsights-core-js" "2.8.9" - "@microsoft/applicationinsights-shims" "2.0.2" - "@microsoft/dynamicproto-js" "^1.1.7" + "@microsoft/applicationinsights-common" "3.0.2" + "@microsoft/applicationinsights-core-js" "3.0.2" + "@microsoft/applicationinsights-shims" "3.0.1" + "@microsoft/dynamicproto-js" "^2.0.2" + "@nevware21/ts-async" ">= 0.2.4 < 2.x" + "@nevware21/ts-utils" ">= 0.9.5 < 2.x" -"@microsoft/applicationinsights-common@2.8.9": - version "2.8.9" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-common/-/applicationinsights-common-2.8.9.tgz#a75e4a3143a7fd797687830c0ddd2069fd900827" - integrity sha512-mObn1moElyxZaGIRF/IU3cOaeKMgxghXnYEoHNUCA2e+rNwBIgxjyKkblFIpmGuHf4X7Oz3o3yBWpaC6AoMpig== +"@microsoft/applicationinsights-common@3.0.2": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-common/-/applicationinsights-common-3.0.2.tgz#37670bb07f4858ed41ff9759119e0759007d6e05" + integrity sha512-y+WXWop+OVim954Cu1uyYMnNx6PWO8okHpZIQi/1YSqtqaYdtJVPv4P0AVzwJdohxzVfgzKvqj9nec/VWqE2Zg== dependencies: - "@microsoft/applicationinsights-core-js" "2.8.9" - "@microsoft/applicationinsights-shims" "2.0.2" - "@microsoft/dynamicproto-js" "^1.1.7" + "@microsoft/applicationinsights-core-js" "3.0.2" + "@microsoft/applicationinsights-shims" "3.0.1" + "@microsoft/dynamicproto-js" "^2.0.2" + "@nevware21/ts-utils" ">= 0.9.5 < 2.x" -"@microsoft/applicationinsights-core-js@2.8.9": - version "2.8.9" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-2.8.9.tgz#0e5d207acfae6986a6fc97249eeb6117e523bf1b" - integrity sha512-HRuIuZ6aOWezcg/G5VyFDDWGL8hDNe/ljPP01J7ImH2kRPEgbtcfPSUMjkamGMefgdq81GZsSoC/NNGTP4pp2w== +"@microsoft/applicationinsights-core-js@2.8.15": + version "2.8.15" + resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-2.8.15.tgz#8fa466474260e01967fe649f14dd9e5ff91dcdc8" + integrity sha512-yYAs9MyjGr2YijQdUSN9mVgT1ijI1FPMgcffpaPmYbHAVbQmF7bXudrBWHxmLzJlwl5rfep+Zgjli2e67lwUqQ== dependencies: "@microsoft/applicationinsights-shims" "2.0.2" - "@microsoft/dynamicproto-js" "^1.1.7" + "@microsoft/dynamicproto-js" "^1.1.9" + +"@microsoft/applicationinsights-core-js@3.0.2": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-3.0.2.tgz#108e20df8c162bec92b1f66f9de2530a25d9f51a" + integrity sha512-WQhVhzlRlLDrQzn3OShCW/pL3BW5WC57t0oywSknX3q7lMzI3jDg7Ihh0iuIcNTzGCTbDkuqr4d6IjEDWIMtJQ== + dependencies: + "@microsoft/applicationinsights-shims" "3.0.1" + "@microsoft/dynamicproto-js" "^2.0.2" + "@nevware21/ts-async" ">= 0.2.4 < 2.x" + "@nevware21/ts-utils" ">= 0.9.5 < 2.x" "@microsoft/applicationinsights-shims@2.0.2", "@microsoft/applicationinsights-shims@^2.0.2": version "2.0.2" resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-shims/-/applicationinsights-shims-2.0.2.tgz#92b36a09375e2d9cb2b4203383b05772be837085" integrity sha512-PoHEgsnmcqruLNHZ/amACqdJ6YYQpED0KSRe6J7gIJTtpZC1FfFU9b1fmDKDKtFoUSrPzEh1qzO3kmRZP0betg== -"@microsoft/applicationinsights-web-basic@^2.8.9": - version "2.8.9" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-web-basic/-/applicationinsights-web-basic-2.8.9.tgz#eed2f3d1e19069962ed2155915c1656e6936e1d5" - integrity sha512-CH0J8JFOy7MjK8JO4pXXU+EML+Ilix+94PMZTX5EJlBU1in+mrik74/8qSg3UC4ekPi12KwrXaHCQSVC3WseXQ== +"@microsoft/applicationinsights-shims@3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-shims/-/applicationinsights-shims-3.0.1.tgz#3865b73ace8405b9c4618cc5c571f2fe3876f06f" + integrity sha512-DKwboF47H1nb33rSUfjqI6ryX29v+2QWcTrRvcQDA32AZr5Ilkr7whOOSsD1aBzwqX0RJEIP1Z81jfE3NBm/Lg== dependencies: - "@microsoft/applicationinsights-channel-js" "2.8.9" - "@microsoft/applicationinsights-common" "2.8.9" - "@microsoft/applicationinsights-core-js" "2.8.9" - "@microsoft/applicationinsights-shims" "2.0.2" - "@microsoft/dynamicproto-js" "^1.1.7" + "@nevware21/ts-utils" ">= 0.9.4 < 2.x" + +"@microsoft/applicationinsights-web-basic@^3.0.2": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-web-basic/-/applicationinsights-web-basic-3.0.2.tgz#f777a4d24b79dde3ae396d3b819e1fce06b7240a" + integrity sha512-6Lq0DE/pZp9RvSV+weGbcxN1NDmfczj6gNPhvZKV2YSQ3RK0LZE3+wjTWLXfuStq8a+nCBdsRpWk8tOKgsoxcg== + dependencies: + "@microsoft/applicationinsights-channel-js" "3.0.2" + "@microsoft/applicationinsights-common" "3.0.2" + "@microsoft/applicationinsights-core-js" "3.0.2" + "@microsoft/applicationinsights-shims" "3.0.1" + "@microsoft/dynamicproto-js" "^2.0.2" + "@nevware21/ts-async" ">= 0.2.4 < 2.x" + "@nevware21/ts-utils" ">= 0.9.5 < 2.x" "@microsoft/applicationinsights-web-snippet@^1.0.1": version "1.0.1" @@ -126,39 +185,74 @@ resolved "https://registry.yarnpkg.com/@microsoft/dynamicproto-js/-/dynamicproto-js-1.1.7.tgz#ede48dd3f85af14ee369c805e5ed5b84222b9fe2" integrity sha512-SK3D3aVt+5vOOccKPnGaJWB5gQ8FuKfjboUJHedMP7gu54HqSCXX5iFXhktGD8nfJb0Go30eDvs/UDoTnR2kOA== -"@opentelemetry/api@^1.0.4": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.2.0.tgz#89ef99401cde6208cff98760b67663726ef26686" - integrity sha512-0nBr+VZNKm9tvNDZFstI3Pq1fCTEDK5OZTnVKNvBNAKgd0yIvmwsP4m61rEv7ZP+tOUjWJhROpxK5MsnlF911g== +"@microsoft/dynamicproto-js@^1.1.9": + version "1.1.9" + resolved "https://registry.yarnpkg.com/@microsoft/dynamicproto-js/-/dynamicproto-js-1.1.9.tgz#7437db7aa061162ee94e4131b69a62b8dad5dea6" + integrity sha512-n1VPsljTSkthsAFYdiWfC+DKzK2WwcRp83Y1YAqdX552BstvsDjft9YXppjUzp11BPsapDoO1LDgrDB0XVsfNQ== -"@opentelemetry/core@1.7.0", "@opentelemetry/core@^1.0.1": - version "1.7.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-1.7.0.tgz#83bdd1b7a4ceafcdffd6590420657caec5f7b34c" - integrity sha512-AVqAi5uc8DrKJBimCTFUT4iFI+5eXpo4sYmGbQ0CypG0piOTHE2g9c5aSoTGYXu3CzOmJZf7pT6Xh+nwm5d6yQ== +"@microsoft/dynamicproto-js@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@microsoft/dynamicproto-js/-/dynamicproto-js-2.0.2.tgz#e57fbec2e7067d48b7e8e1e1c1d354028ef718a6" + integrity sha512-MB8trWaFREpmb037k/d0bB7T2BP7Ai24w1e1tbz3ASLB0/lwphsq3Nq8S9I5AsI5vs4zAQT+SB5nC5/dLYTiOg== dependencies: - "@opentelemetry/semantic-conventions" "1.7.0" + "@nevware21/ts-utils" ">= 0.9.4 < 2.x" -"@opentelemetry/resources@1.7.0": - version "1.7.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/resources/-/resources-1.7.0.tgz#90ccd3a6a86b4dfba4e833e73944bd64958d78c5" - integrity sha512-u1M0yZotkjyKx8dj+46Sg5thwtOTBmtRieNXqdCRiWUp6SfFiIP0bI+1XK3LhuXqXkBXA1awJZaTqKduNMStRg== +"@nevware21/ts-async@>= 0.2.4 < 2.x": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@nevware21/ts-async/-/ts-async-0.3.0.tgz#a8b97ba01065fc930de9a3f4dd4a05e862becc6c" + integrity sha512-ZUcgUH12LN/F6nzN0cYd0F/rJaMLmXr0EHVTyYfaYmK55bdwE4338uue4UiVoRqHVqNW4KDUrJc49iGogHKeWA== dependencies: - "@opentelemetry/core" "1.7.0" - "@opentelemetry/semantic-conventions" "1.7.0" + "@nevware21/ts-utils" ">= 0.10.0 < 2.x" -"@opentelemetry/sdk-trace-base@^1.0.1": - version "1.7.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.7.0.tgz#b498424e0c6340a9d80de63fd408c5c2130a60a5" - integrity sha512-Iz84C+FVOskmauh9FNnj4+VrA+hG5o+tkMzXuoesvSfunVSioXib0syVFeNXwOm4+M5GdWCuW632LVjqEXStIg== +"@nevware21/ts-utils@>= 0.10.0 < 2.x", "@nevware21/ts-utils@>= 0.9.4 < 2.x", "@nevware21/ts-utils@>= 0.9.5 < 2.x": + version "0.10.1" + resolved "https://registry.yarnpkg.com/@nevware21/ts-utils/-/ts-utils-0.10.1.tgz#aa65abc71eba06749a396598f22263d26f796ac7" + integrity sha512-pMny25NnF2/MJwdqC3Iyjm2pGIXNxni4AROpcqDeWa+td9JMUY4bUS9uU9XW+BoBRqTLUL+WURF9SOd/6OQzRg== + +"@opentelemetry/api@^1.4.1": + version "1.4.1" + resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.4.1.tgz#ff22eb2e5d476fbc2450a196e40dd243cc20c28f" + integrity sha512-O2yRJce1GOc6PAy3QxFM4NzFiWzvScDC1/5ihYBL6BUEVdq0XMWN01sppE+H6bBXbaFYipjwFLEWLg5PaSOThA== + +"@opentelemetry/core@1.15.2", "@opentelemetry/core@^1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-1.15.2.tgz#5b170bf223a2333884bbc2d29d95812cdbda7c9f" + integrity sha512-+gBv15ta96WqkHZaPpcDHiaz0utiiHZVfm2YOYSqFGrUaJpPkMoSuLBB58YFQGi6Rsb9EHos84X6X5+9JspmLw== dependencies: - "@opentelemetry/core" "1.7.0" - "@opentelemetry/resources" "1.7.0" - "@opentelemetry/semantic-conventions" "1.7.0" + "@opentelemetry/semantic-conventions" "1.15.2" -"@opentelemetry/semantic-conventions@1.7.0", "@opentelemetry/semantic-conventions@^1.0.1": - version "1.7.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.7.0.tgz#af80a1ef7cf110ea3a68242acd95648991bcd763" - integrity sha512-FGBx/Qd09lMaqQcogCHyYrFEpTx4cAjeS+48lMIR12z7LdH+zofGDVQSubN59nL6IpubfKqTeIDu9rNO28iHVA== +"@opentelemetry/instrumentation@^0.41.2": + version "0.41.2" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation/-/instrumentation-0.41.2.tgz#cae11fa64485dcf03dae331f35b315b64bc6189f" + integrity sha512-rxU72E0pKNH6ae2w5+xgVYZLzc5mlxAbGzF4shxMVK8YC2QQsfN38B2GPbj0jvrKWWNUElfclQ+YTykkNg/grw== + dependencies: + "@types/shimmer" "^1.0.2" + import-in-the-middle "1.4.2" + require-in-the-middle "^7.1.1" + semver "^7.5.1" + shimmer "^1.2.1" + +"@opentelemetry/resources@1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@opentelemetry/resources/-/resources-1.15.2.tgz#0c9e26cb65652a1402834a3c030cce6028d6dd9d" + integrity sha512-xmMRLenT9CXmm5HMbzpZ1hWhaUowQf8UB4jMjFlAxx1QzQcsD3KFNAVX/CAWzFPtllTyTplrA4JrQ7sCH3qmYw== + dependencies: + "@opentelemetry/core" "1.15.2" + "@opentelemetry/semantic-conventions" "1.15.2" + +"@opentelemetry/sdk-trace-base@^1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.15.2.tgz#4821f94033c55a6c8bbd35ae387b715b6108517a" + integrity sha512-BEaxGZbWtvnSPchV98qqqqa96AOcb41pjgvhfzDij10tkBhIu9m0Jd6tZ1tJB5ZHfHbTffqYVYE0AOGobec/EQ== + dependencies: + "@opentelemetry/core" "1.15.2" + "@opentelemetry/resources" "1.15.2" + "@opentelemetry/semantic-conventions" "1.15.2" + +"@opentelemetry/semantic-conventions@1.15.2", "@opentelemetry/semantic-conventions@^1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.15.2.tgz#3bafb5de3e20e841dff6cb3c66f4d6e9694c4241" + integrity sha512-CjbOKwk2s+3xPIMcd5UNYQzsf+v94RczbdNix9/kQh38WiQkM90sUOi3if8eyHFgiBjBjhwXrA7W3ydiSQP9mw== "@tootallnate/once@2": version "2.0.0" @@ -183,15 +277,30 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-18.15.13.tgz#f64277c341150c979e42b00e4ac289290c9df469" integrity sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q== -"@vscode/extension-telemetry@0.7.5": - version "0.7.5" - resolved "https://registry.yarnpkg.com/@vscode/extension-telemetry/-/extension-telemetry-0.7.5.tgz#bf965731816e08c3f146f96d901ec67954fc913b" - integrity sha512-fJ5y3TcpqqkFYHneabYaoB4XAhDdVflVm+TDKshw9VOs77jkgNS4UA7LNXrWeO0eDne3Sh3JgURf+xzc1rk69w== +"@types/shimmer@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@types/shimmer/-/shimmer-1.0.2.tgz#93eb2c243c351f3f17d5c580c7467ae5d686b65f" + integrity sha512-dKkr1bTxbEsFlh2ARpKzcaAmsYixqt9UyCdoEZk8rHyE4iQYcDCyvSjDSf7JUWJHlJiTtbIoQjxKh6ViywqDAg== + +"@vscode/extension-telemetry@^0.8.4": + version "0.8.4" + resolved "https://registry.yarnpkg.com/@vscode/extension-telemetry/-/extension-telemetry-0.8.4.tgz#c078c6f55df1c9e0592de3b4ce0f685dd345bfe7" + integrity sha512-UqM9+KZDDK3MyoHTsg6XNM+XO6pweQxzCpqJz33BoBEYAGsbBviRYcVpJglgay2oReuDD2pOI1Nio3BKNDLhWA== dependencies: - "@microsoft/1ds-core-js" "^3.2.8" - "@microsoft/1ds-post-js" "^3.2.8" - "@microsoft/applicationinsights-web-basic" "^2.8.9" - applicationinsights "2.4.1" + "@microsoft/1ds-core-js" "^3.2.13" + "@microsoft/1ds-post-js" "^3.2.13" + "@microsoft/applicationinsights-web-basic" "^3.0.2" + applicationinsights "^2.7.1" + +acorn-import-assertions@^1.9.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz#507276249d684797c84e0734ef84860334cfb1ac" + integrity sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA== + +acorn@^8.8.2: + version "8.10.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5" + integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw== agent-base@6: version "6.0.2" @@ -200,22 +309,24 @@ agent-base@6: dependencies: debug "4" -applicationinsights@2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/applicationinsights/-/applicationinsights-2.4.1.tgz#4de4c4dd3c7c4a44445cfbf3d15808fc0dcc423d" - integrity sha512-0n0Ikd0gzSm460xm+M0UTWIwXrhrH/0bqfZatcJjYObWyefxfAxapGEyNnSGd1Tg90neHz+Yhf+Ff/zgvPiQYA== +applicationinsights@^2.7.1: + version "2.7.3" + resolved "https://registry.yarnpkg.com/applicationinsights/-/applicationinsights-2.7.3.tgz#8781454d29c0b14c9773f2e892b4cf5e7468ffa5" + integrity sha512-JY8+kTEkjbA+kAVNWDtpfW2lqsrDALfDXuxOs74KLPu2y13fy/9WB52V4LfYVTVcW1/jYOXjTxNS2gPZIDh1iw== dependencies: - "@azure/core-auth" "^1.4.0" - "@azure/core-rest-pipeline" "^1.10.0" + "@azure/core-auth" "^1.5.0" + "@azure/core-rest-pipeline" "1.10.1" + "@azure/core-util" "1.2.0" + "@azure/opentelemetry-instrumentation-azure-sdk" "^1.0.0-beta.5" "@microsoft/applicationinsights-web-snippet" "^1.0.1" - "@opentelemetry/api" "^1.0.4" - "@opentelemetry/core" "^1.0.1" - "@opentelemetry/sdk-trace-base" "^1.0.1" - "@opentelemetry/semantic-conventions" "^1.0.1" + "@opentelemetry/api" "^1.4.1" + "@opentelemetry/core" "^1.15.2" + "@opentelemetry/sdk-trace-base" "^1.15.2" + "@opentelemetry/semantic-conventions" "^1.15.2" cls-hooked "^4.2.2" continuation-local-storage "^3.2.1" - diagnostic-channel "1.1.0" - diagnostic-channel-publishers "1.0.5" + diagnostic-channel "1.1.1" + diagnostic-channel-publishers "1.0.7" async-hook-jl@^1.7.6: version "1.7.6" @@ -244,6 +355,11 @@ axios@^0.26.1: dependencies: follow-redirects "^1.14.8" +cjs-module-lexer@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz#6c370ab19f8a3394e318fe682686ec0ac684d107" + integrity sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ== + cls-hooked@^4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/cls-hooked/-/cls-hooked-4.2.2.tgz#ad2e9a4092680cdaffeb2d3551da0e225eae1908" @@ -268,7 +384,7 @@ continuation-local-storage@^3.2.1: async-listener "^0.6.0" emitter-listener "^1.1.1" -debug@4: +debug@4, debug@^4.1.1: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== @@ -280,17 +396,17 @@ delayed-stream@~1.0.0: resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= -diagnostic-channel-publishers@1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/diagnostic-channel-publishers/-/diagnostic-channel-publishers-1.0.5.tgz#df8c317086c50f5727fdfb5d2fce214d2e4130ae" - integrity sha512-dJwUS0915pkjjimPJVDnS/QQHsH0aOYhnZsLJdnZIMOrB+csj8RnZhWTuwnm8R5v3Z7OZs+ksv5luC14DGB7eg== +diagnostic-channel-publishers@1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/diagnostic-channel-publishers/-/diagnostic-channel-publishers-1.0.7.tgz#9b7f8d5ee1295481aee19c827d917e96fedf2c4a" + integrity sha512-SEECbY5AiVt6DfLkhkaHNeshg1CogdLLANA8xlG/TKvS+XUgvIKl7VspJGYiEdL5OUyzMVnr7o0AwB7f+/Mjtg== -diagnostic-channel@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/diagnostic-channel/-/diagnostic-channel-1.1.0.tgz#6985e9dfedfbc072d91dc4388477e4087147756e" - integrity sha512-fwujyMe1gj6rk6dYi9hMZm0c8Mz8NDMVl2LB4iaYh3+LIAThZC8RKFGXWG0IML2OxAit/ZFRgZhMkhQ3d/bobQ== +diagnostic-channel@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/diagnostic-channel/-/diagnostic-channel-1.1.1.tgz#44b60972de9ee055c16216535b0e9db3f6a0efd0" + integrity sha512-r2HV5qFkUICyoaKlBEpLKHjxMXATUf/l+h8UZPGBHGLy4DDiY2sOLcIctax4eRnTw5wH2jTMExLntGPJ8eOJxw== dependencies: - semver "^5.3.0" + semver "^7.5.3" emitter-listener@^1.0.1, emitter-listener@^1.1.1: version "1.1.2" @@ -322,6 +438,18 @@ form-data@^4.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + http-proxy-agent@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz#5129800203520d434f142bc78ff3c170800f2b43" @@ -339,6 +467,30 @@ https-proxy-agent@^5.0.0: agent-base "6" debug "4" +import-in-the-middle@1.4.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/import-in-the-middle/-/import-in-the-middle-1.4.2.tgz#2a266676e3495e72c04bbaa5ec14756ba168391b" + integrity sha512-9WOz1Yh/cvO/p69sxRmhyQwrIGGSp7EIdcb+fFNVi7CzQGQB8U1/1XrKVSbEd/GNOAeM0peJtmi7+qphe7NvAw== + dependencies: + acorn "^8.8.2" + acorn-import-assertions "^1.9.0" + cjs-module-lexer "^1.2.2" + module-details-from-path "^1.0.3" + +is-core-module@^2.13.0: + version "2.13.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.0.tgz#bb52aa6e2cbd49a30c2ba68c42bf3435ba6072db" + integrity sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ== + dependencies: + has "^1.0.3" + +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + mime-db@1.44.0: version "1.44.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.44.0.tgz#fa11c5eb0aca1334b4233cb4d52f10c5a6272f92" @@ -351,6 +503,11 @@ mime-types@^2.1.12: dependencies: mime-db "1.44.0" +module-details-from-path@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/module-details-from-path/-/module-details-from-path-1.0.3.tgz#114c949673e2a8a35e9d35788527aa37b679da2b" + integrity sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A== + ms@2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" @@ -363,12 +520,42 @@ node-fetch@2.6.7: dependencies: whatwg-url "^5.0.0" +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +require-in-the-middle@^7.1.1: + version "7.2.0" + resolved "https://registry.yarnpkg.com/require-in-the-middle/-/require-in-the-middle-7.2.0.tgz#b539de8f00955444dc8aed95e17c69b0a4f10fcf" + integrity sha512-3TLx5TGyAY6AOqLBoXmHkNql0HIf2RGbuMgCDT2WO/uGVAPJs6h7Kl+bN6TIZGd9bWhWPwnDnTHGtW8Iu77sdw== + dependencies: + debug "^4.1.1" + module-details-from-path "^1.0.3" + resolve "^1.22.1" + +resolve@^1.22.1: + version "1.22.4" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.4.tgz#1dc40df46554cdaf8948a486a10f6ba1e2026c34" + integrity sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg== + dependencies: + is-core-module "^2.13.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + semver@^5.3.0, semver@^5.4.1: version "5.7.2" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== -shimmer@^1.1.0, shimmer@^1.2.0: +semver@^7.5.1, semver@^7.5.3: + version "7.5.4" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" + integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== + dependencies: + lru-cache "^6.0.0" + +shimmer@^1.1.0, shimmer@^1.2.0, shimmer@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/shimmer/-/shimmer-1.2.1.tgz#610859f7de327b587efebf501fb43117f9aff337" integrity sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw== @@ -378,6 +565,11 @@ stack-chain@^1.3.7: resolved "https://registry.yarnpkg.com/stack-chain/-/stack-chain-1.3.7.tgz#d192c9ff4ea6a22c94c4dd459171e3f00cea1285" integrity sha512-D8cWtWVdIe/jBA7v5p5Hwl5yOSOrmZPWDPe2KxQ5UAGD+nxbxU0lKXA4h85Ta6+qgdKVL3vUxsbIZjc1kBG7ug== +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + tas-client@0.1.45: version "0.1.45" resolved "https://registry.yarnpkg.com/tas-client/-/tas-client-0.1.45.tgz#83bbf73f8458a0f527f9a389f7e1c37f63a64a76" @@ -419,3 +611,8 @@ whatwg-url@^5.0.0: dependencies: tr46 "~0.0.3" webidl-conversions "^3.0.0" + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== diff --git a/extensions/github/package.json b/extensions/github/package.json index ec02df2ec85..afbb7253f7f 100644 --- a/extensions/github/package.json +++ b/extensions/github/package.json @@ -183,7 +183,7 @@ "@octokit/graphql-schema": "14.4.0", "@octokit/rest": "19.0.4", "tunnel": "^0.0.6", - "@vscode/extension-telemetry": "0.7.5" + "@vscode/extension-telemetry": "^0.8.4" }, "devDependencies": { "@types/node": "18.x" diff --git a/extensions/github/yarn.lock b/extensions/github/yarn.lock index f562d36c972..ab4275a38b9 100644 --- a/extensions/github/yarn.lock +++ b/extensions/github/yarn.lock @@ -17,32 +17,50 @@ "@azure/abort-controller" "^1.0.0" tslib "^2.2.0" -"@azure/core-rest-pipeline@^1.10.0": - version "1.11.0" - resolved "https://registry.yarnpkg.com/@azure/core-rest-pipeline/-/core-rest-pipeline-1.11.0.tgz#fc0e8f56caac08a9d4ac91c07a6c5a360ea31c82" - integrity sha512-nB4KXl6qAyJmBVLWA7SakT4tzpYZTCk4pvRBeI+Ye0WYSOrlTqlMhc4MSS/8atD3ufeYWdkN380LLoXlUUzThw== +"@azure/core-auth@^1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@azure/core-auth/-/core-auth-1.5.0.tgz#a41848c5c31cb3b7c84c409885267d55a2c92e44" + integrity sha512-udzoBuYG1VBoHVohDTrvKjyzel34zt77Bhp7dQntVGGD0ehVq48owENbBG8fIgkHRNUBQH5k1r0hpoMu5L8+kw== + dependencies: + "@azure/abort-controller" "^1.0.0" + "@azure/core-util" "^1.1.0" + tslib "^2.2.0" + +"@azure/core-rest-pipeline@1.10.1": + version "1.10.1" + resolved "https://registry.yarnpkg.com/@azure/core-rest-pipeline/-/core-rest-pipeline-1.10.1.tgz#348290847ca31b9eecf9cf5de7519aaccdd30968" + integrity sha512-Kji9k6TOFRDB5ZMTw8qUf2IJ+CeJtsuMdAHox9eqpTf1cefiNMpzrfnF6sINEBZJsaVaWgQ0o48B6kcUH68niA== dependencies: "@azure/abort-controller" "^1.0.0" "@azure/core-auth" "^1.4.0" "@azure/core-tracing" "^1.0.1" - "@azure/core-util" "^1.3.0" + "@azure/core-util" "^1.0.0" "@azure/logger" "^1.0.0" form-data "^4.0.0" http-proxy-agent "^5.0.0" https-proxy-agent "^5.0.0" tslib "^2.2.0" + uuid "^8.3.0" -"@azure/core-tracing@^1.0.1": +"@azure/core-tracing@^1.0.0", "@azure/core-tracing@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@azure/core-tracing/-/core-tracing-1.0.1.tgz#352a38cbea438c4a83c86b314f48017d70ba9503" integrity sha512-I5CGMoLtX+pI17ZdiFJZgxMJApsK6jjfm85hpgp3oazCdq5Wxgh4wMr7ge/TTWW1B5WBuvIOI1fMU/FrOAMKrw== dependencies: tslib "^2.2.0" -"@azure/core-util@^1.3.0": - version "1.3.2" - resolved "https://registry.yarnpkg.com/@azure/core-util/-/core-util-1.3.2.tgz#3f8cfda1e87fac0ce84f8c1a42fcd6d2a986632d" - integrity sha512-2bECOUh88RvL1pMZTcc6OzfobBeWDBf5oBbhjIhT1MV9otMVWCzpOJkkiKtrnO88y5GGBelgY8At73KGAdbkeQ== +"@azure/core-util@1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@azure/core-util/-/core-util-1.2.0.tgz#3499deba1fc36dda6f1912b791809b6f15d4a392" + integrity sha512-ffGIw+Qs8bNKNLxz5UPkz4/VBM/EZY07mPve1ZYFqYUdPwFqRj0RPk0U7LZMOfT7GCck9YjuT1Rfp1PApNl1ng== + dependencies: + "@azure/abort-controller" "^1.0.0" + tslib "^2.2.0" + +"@azure/core-util@^1.0.0", "@azure/core-util@^1.1.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@azure/core-util/-/core-util-1.4.0.tgz#c120a56b3e48a9e4d20619a0b00268ae9de891c7" + integrity sha512-eGAyJpm3skVQoLiRqm/xPa+SXi/NPDdSHMxbRAz2lSprd+Zs+qrpQGQQ2VQ3Nttu+nSZR4XoYQC71LbEI7jsig== dependencies: "@azure/abort-controller" "^1.0.0" tslib "^2.2.0" @@ -54,66 +72,100 @@ dependencies: tslib "^2.2.0" -"@microsoft/1ds-core-js@3.2.12", "@microsoft/1ds-core-js@^3.2.8": - version "3.2.12" - resolved "https://registry.yarnpkg.com/@microsoft/1ds-core-js/-/1ds-core-js-3.2.12.tgz#f5f56626bd0385a357fae6f730eea347be02ce64" - integrity sha512-cHpxZZ+pbtOyqFMFB/c1COpaOE3VPFU6phYVHVvOA9DvoeMZfI/Xrxaj7B/vfq4MmkiE7nOAPhv5ZRn+i6OogA== +"@azure/opentelemetry-instrumentation-azure-sdk@^1.0.0-beta.5": + version "1.0.0-beta.5" + resolved "https://registry.yarnpkg.com/@azure/opentelemetry-instrumentation-azure-sdk/-/opentelemetry-instrumentation-azure-sdk-1.0.0-beta.5.tgz#78809e6c005d08450701e5d37f087f6fce2f86eb" + integrity sha512-fsUarKQDvjhmBO4nIfaZkfNSApm1hZBzcvpNbSrXdcUBxu7lRvKsV5DnwszX7cnhLyVOW9yl1uigtRQ1yDANjA== dependencies: - "@microsoft/applicationinsights-core-js" "2.8.14" + "@azure/core-tracing" "^1.0.0" + "@azure/logger" "^1.0.0" + "@opentelemetry/api" "^1.4.1" + "@opentelemetry/core" "^1.15.2" + "@opentelemetry/instrumentation" "^0.41.2" + tslib "^2.2.0" + +"@microsoft/1ds-core-js@3.2.13", "@microsoft/1ds-core-js@^3.2.13": + version "3.2.13" + resolved "https://registry.yarnpkg.com/@microsoft/1ds-core-js/-/1ds-core-js-3.2.13.tgz#0c105ed75091bae3f1555c0334704fa9911c58fb" + integrity sha512-CluYTRWcEk0ObG5EWFNWhs87e2qchJUn0p2D21ZUa3PWojPZfPSBs4//WIE0MYV8Qg1Hdif2ZTwlM7TbYUjfAg== + dependencies: + "@microsoft/applicationinsights-core-js" "2.8.15" "@microsoft/applicationinsights-shims" "^2.0.2" "@microsoft/dynamicproto-js" "^1.1.7" -"@microsoft/1ds-post-js@^3.2.8": - version "3.2.12" - resolved "https://registry.yarnpkg.com/@microsoft/1ds-post-js/-/1ds-post-js-3.2.12.tgz#60f6ff48ba48c88880c1bceb376711cdd34f87ea" - integrity sha512-vhIVYg4FzBfwtM8tBqDUq3xU+cFu6SQ7biuJHtQpd5PVjDgvAovVOMRF1khsZE/k2rttRRBpmBgNEqG3Ptoysw== +"@microsoft/1ds-post-js@^3.2.13": + version "3.2.13" + resolved "https://registry.yarnpkg.com/@microsoft/1ds-post-js/-/1ds-post-js-3.2.13.tgz#560aacac8a92fdbb79e8c2ebcb293d56e19f51aa" + integrity sha512-HgS574fdD19Bo2vPguyznL4eDw7Pcm1cVNpvbvBLWiW3x4e1FCQ3VMXChWnAxCae8Hb0XqlA2sz332ZobBavTA== dependencies: - "@microsoft/1ds-core-js" "3.2.12" + "@microsoft/1ds-core-js" "3.2.13" "@microsoft/applicationinsights-shims" "^2.0.2" "@microsoft/dynamicproto-js" "^1.1.7" -"@microsoft/applicationinsights-channel-js@2.8.14": - version "2.8.14" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-channel-js/-/applicationinsights-channel-js-2.8.14.tgz#daabd8a418d9b70a318c0126518e000dd6f67fa0" - integrity sha512-z1AG6lqV3ACtdUXnT0Ubj48BAZ8K01sFsYdWgroSXpw2lYUlXAzdx3tK8zpaqEXSEhok8CWTZki7aunHzkZHSw== +"@microsoft/applicationinsights-channel-js@3.0.2": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-channel-js/-/applicationinsights-channel-js-3.0.2.tgz#be49fbf74831c7b8c97950027c5052ea99d2a8a5" + integrity sha512-jDBNKbCHsJgmpv0CKNhJ/uN9ZphvfGdb93Svk+R4LjO8L3apNNMbDDPxBvXXi0uigRmA1TBcmyBG4IRKjabGhw== + dependencies: + "@microsoft/applicationinsights-common" "3.0.2" + "@microsoft/applicationinsights-core-js" "3.0.2" + "@microsoft/applicationinsights-shims" "3.0.1" + "@microsoft/dynamicproto-js" "^2.0.2" + "@nevware21/ts-async" ">= 0.2.4 < 2.x" + "@nevware21/ts-utils" ">= 0.9.5 < 2.x" + +"@microsoft/applicationinsights-common@3.0.2": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-common/-/applicationinsights-common-3.0.2.tgz#37670bb07f4858ed41ff9759119e0759007d6e05" + integrity sha512-y+WXWop+OVim954Cu1uyYMnNx6PWO8okHpZIQi/1YSqtqaYdtJVPv4P0AVzwJdohxzVfgzKvqj9nec/VWqE2Zg== + dependencies: + "@microsoft/applicationinsights-core-js" "3.0.2" + "@microsoft/applicationinsights-shims" "3.0.1" + "@microsoft/dynamicproto-js" "^2.0.2" + "@nevware21/ts-utils" ">= 0.9.5 < 2.x" + +"@microsoft/applicationinsights-core-js@2.8.15": + version "2.8.15" + resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-2.8.15.tgz#8fa466474260e01967fe649f14dd9e5ff91dcdc8" + integrity sha512-yYAs9MyjGr2YijQdUSN9mVgT1ijI1FPMgcffpaPmYbHAVbQmF7bXudrBWHxmLzJlwl5rfep+Zgjli2e67lwUqQ== dependencies: - "@microsoft/applicationinsights-common" "2.8.14" - "@microsoft/applicationinsights-core-js" "2.8.14" "@microsoft/applicationinsights-shims" "2.0.2" "@microsoft/dynamicproto-js" "^1.1.9" -"@microsoft/applicationinsights-common@2.8.14": - version "2.8.14" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-common/-/applicationinsights-common-2.8.14.tgz#7d082295f862a189c80aa98b3f4aaec926546051" - integrity sha512-1xjJvyyRN7tb5ahOTkEGGsvw8zvqmS714y3+1m7ooKHFfxO0wX+eYOU/kke74BCY0nJ/pocB/6hjWZOgwvbHig== +"@microsoft/applicationinsights-core-js@3.0.2": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-3.0.2.tgz#108e20df8c162bec92b1f66f9de2530a25d9f51a" + integrity sha512-WQhVhzlRlLDrQzn3OShCW/pL3BW5WC57t0oywSknX3q7lMzI3jDg7Ihh0iuIcNTzGCTbDkuqr4d6IjEDWIMtJQ== dependencies: - "@microsoft/applicationinsights-core-js" "2.8.14" - "@microsoft/applicationinsights-shims" "2.0.2" - "@microsoft/dynamicproto-js" "^1.1.9" - -"@microsoft/applicationinsights-core-js@2.8.14": - version "2.8.14" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-2.8.14.tgz#80e3d9d42102e741494726d78ac923098bad7132" - integrity sha512-XacWUHdjSHMUwdngMZBp0oiCBifD56CQK2Egu2PiBiF4xu2AO2yNCtWSXsQX2g5OkEhVwaEjfa/aH3WbpYxB1g== - dependencies: - "@microsoft/applicationinsights-shims" "2.0.2" - "@microsoft/dynamicproto-js" "^1.1.9" + "@microsoft/applicationinsights-shims" "3.0.1" + "@microsoft/dynamicproto-js" "^2.0.2" + "@nevware21/ts-async" ">= 0.2.4 < 2.x" + "@nevware21/ts-utils" ">= 0.9.5 < 2.x" "@microsoft/applicationinsights-shims@2.0.2", "@microsoft/applicationinsights-shims@^2.0.2": version "2.0.2" resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-shims/-/applicationinsights-shims-2.0.2.tgz#92b36a09375e2d9cb2b4203383b05772be837085" integrity sha512-PoHEgsnmcqruLNHZ/amACqdJ6YYQpED0KSRe6J7gIJTtpZC1FfFU9b1fmDKDKtFoUSrPzEh1qzO3kmRZP0betg== -"@microsoft/applicationinsights-web-basic@^2.8.9": - version "2.8.14" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-web-basic/-/applicationinsights-web-basic-2.8.14.tgz#8c43bcad2e12f25eb00a9aaad0182371507b21b9" - integrity sha512-R2mzg5NmCtLloq3lPQFmnlvjrPIqm3mWNYVy5ELJuOPZ7S6j9y7s4yHOzfXynmOziiQd+0q1j9pTth9aP9vo0g== +"@microsoft/applicationinsights-shims@3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-shims/-/applicationinsights-shims-3.0.1.tgz#3865b73ace8405b9c4618cc5c571f2fe3876f06f" + integrity sha512-DKwboF47H1nb33rSUfjqI6ryX29v+2QWcTrRvcQDA32AZr5Ilkr7whOOSsD1aBzwqX0RJEIP1Z81jfE3NBm/Lg== dependencies: - "@microsoft/applicationinsights-channel-js" "2.8.14" - "@microsoft/applicationinsights-common" "2.8.14" - "@microsoft/applicationinsights-core-js" "2.8.14" - "@microsoft/applicationinsights-shims" "2.0.2" - "@microsoft/dynamicproto-js" "^1.1.9" + "@nevware21/ts-utils" ">= 0.9.4 < 2.x" + +"@microsoft/applicationinsights-web-basic@^3.0.2": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-web-basic/-/applicationinsights-web-basic-3.0.2.tgz#f777a4d24b79dde3ae396d3b819e1fce06b7240a" + integrity sha512-6Lq0DE/pZp9RvSV+weGbcxN1NDmfczj6gNPhvZKV2YSQ3RK0LZE3+wjTWLXfuStq8a+nCBdsRpWk8tOKgsoxcg== + dependencies: + "@microsoft/applicationinsights-channel-js" "3.0.2" + "@microsoft/applicationinsights-common" "3.0.2" + "@microsoft/applicationinsights-core-js" "3.0.2" + "@microsoft/applicationinsights-shims" "3.0.1" + "@microsoft/dynamicproto-js" "^2.0.2" + "@nevware21/ts-async" ">= 0.2.4 < 2.x" + "@nevware21/ts-utils" ">= 0.9.5 < 2.x" "@microsoft/applicationinsights-web-snippet@^1.0.1": version "1.0.1" @@ -125,6 +177,25 @@ resolved "https://registry.yarnpkg.com/@microsoft/dynamicproto-js/-/dynamicproto-js-1.1.9.tgz#7437db7aa061162ee94e4131b69a62b8dad5dea6" integrity sha512-n1VPsljTSkthsAFYdiWfC+DKzK2WwcRp83Y1YAqdX552BstvsDjft9YXppjUzp11BPsapDoO1LDgrDB0XVsfNQ== +"@microsoft/dynamicproto-js@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@microsoft/dynamicproto-js/-/dynamicproto-js-2.0.2.tgz#e57fbec2e7067d48b7e8e1e1c1d354028ef718a6" + integrity sha512-MB8trWaFREpmb037k/d0bB7T2BP7Ai24w1e1tbz3ASLB0/lwphsq3Nq8S9I5AsI5vs4zAQT+SB5nC5/dLYTiOg== + dependencies: + "@nevware21/ts-utils" ">= 0.9.4 < 2.x" + +"@nevware21/ts-async@>= 0.2.4 < 2.x": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@nevware21/ts-async/-/ts-async-0.3.0.tgz#a8b97ba01065fc930de9a3f4dd4a05e862becc6c" + integrity sha512-ZUcgUH12LN/F6nzN0cYd0F/rJaMLmXr0EHVTyYfaYmK55bdwE4338uue4UiVoRqHVqNW4KDUrJc49iGogHKeWA== + dependencies: + "@nevware21/ts-utils" ">= 0.10.0 < 2.x" + +"@nevware21/ts-utils@>= 0.10.0 < 2.x", "@nevware21/ts-utils@>= 0.9.4 < 2.x", "@nevware21/ts-utils@>= 0.9.5 < 2.x": + version "0.10.1" + resolved "https://registry.yarnpkg.com/@nevware21/ts-utils/-/ts-utils-0.10.1.tgz#aa65abc71eba06749a396598f22263d26f796ac7" + integrity sha512-pMny25NnF2/MJwdqC3Iyjm2pGIXNxni4AROpcqDeWa+td9JMUY4bUS9uU9XW+BoBRqTLUL+WURF9SOd/6OQzRg== + "@octokit/auth-token@^3.0.0": version "3.0.1" resolved "https://registry.yarnpkg.com/@octokit/auth-token/-/auth-token-3.0.1.tgz#88bc2baf5d706cb258474e722a720a8365dff2ec" @@ -255,39 +326,50 @@ dependencies: "@octokit/openapi-types" "^17.1.0" -"@opentelemetry/api@^1.0.4": +"@opentelemetry/api@^1.4.1": version "1.4.1" resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.4.1.tgz#ff22eb2e5d476fbc2450a196e40dd243cc20c28f" integrity sha512-O2yRJce1GOc6PAy3QxFM4NzFiWzvScDC1/5ihYBL6BUEVdq0XMWN01sppE+H6bBXbaFYipjwFLEWLg5PaSOThA== -"@opentelemetry/core@1.14.0", "@opentelemetry/core@^1.0.1": - version "1.14.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-1.14.0.tgz#64e876b29cb736c984d54164cd47433f513eafd3" - integrity sha512-MnMZ+sxsnlzloeuXL2nm5QcNczt/iO82UOeQQDHhV83F2fP3sgntW2evvtoxJki0MBLxEsh5ADD7PR/Hn5uzjw== +"@opentelemetry/core@1.15.2", "@opentelemetry/core@^1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-1.15.2.tgz#5b170bf223a2333884bbc2d29d95812cdbda7c9f" + integrity sha512-+gBv15ta96WqkHZaPpcDHiaz0utiiHZVfm2YOYSqFGrUaJpPkMoSuLBB58YFQGi6Rsb9EHos84X6X5+9JspmLw== dependencies: - "@opentelemetry/semantic-conventions" "1.14.0" + "@opentelemetry/semantic-conventions" "1.15.2" -"@opentelemetry/resources@1.14.0": - version "1.14.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/resources/-/resources-1.14.0.tgz#d6b0a4e71c2706d33c8c6ec7a7b8fea6ad27ddea" - integrity sha512-qRfWIgBxxl3z47E036Aey0Lj2ZjlFb27Q7Xnj1y1z/P293RXJZGLtcfn/w8JF7v1Q2hs3SDGxz7Wb9Dko1YUQA== +"@opentelemetry/instrumentation@^0.41.2": + version "0.41.2" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation/-/instrumentation-0.41.2.tgz#cae11fa64485dcf03dae331f35b315b64bc6189f" + integrity sha512-rxU72E0pKNH6ae2w5+xgVYZLzc5mlxAbGzF4shxMVK8YC2QQsfN38B2GPbj0jvrKWWNUElfclQ+YTykkNg/grw== dependencies: - "@opentelemetry/core" "1.14.0" - "@opentelemetry/semantic-conventions" "1.14.0" + "@types/shimmer" "^1.0.2" + import-in-the-middle "1.4.2" + require-in-the-middle "^7.1.1" + semver "^7.5.1" + shimmer "^1.2.1" -"@opentelemetry/sdk-trace-base@^1.0.1": - version "1.14.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.14.0.tgz#831af08f002228a11e577ff860eb6059c8b80fb7" - integrity sha512-NzRGt3PS+HPKfQYMb6Iy8YYc5OKA73qDwci/6ujOIvyW9vcqBJSWbjZ8FeLEAmuatUB5WrRhEKu9b0sIiIYTrQ== +"@opentelemetry/resources@1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@opentelemetry/resources/-/resources-1.15.2.tgz#0c9e26cb65652a1402834a3c030cce6028d6dd9d" + integrity sha512-xmMRLenT9CXmm5HMbzpZ1hWhaUowQf8UB4jMjFlAxx1QzQcsD3KFNAVX/CAWzFPtllTyTplrA4JrQ7sCH3qmYw== dependencies: - "@opentelemetry/core" "1.14.0" - "@opentelemetry/resources" "1.14.0" - "@opentelemetry/semantic-conventions" "1.14.0" + "@opentelemetry/core" "1.15.2" + "@opentelemetry/semantic-conventions" "1.15.2" -"@opentelemetry/semantic-conventions@1.14.0", "@opentelemetry/semantic-conventions@^1.0.1": - version "1.14.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.14.0.tgz#6a729b7f372ce30f77a3f217c09bc216f863fccb" - integrity sha512-rJfCY8rCWz3cb4KI6pEofnytvMPuj3YLQwoscCCYZ5DkdiPjo15IQ0US7+mjcWy9H3fcZIzf2pbJZ7ck/h4tug== +"@opentelemetry/sdk-trace-base@^1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.15.2.tgz#4821f94033c55a6c8bbd35ae387b715b6108517a" + integrity sha512-BEaxGZbWtvnSPchV98qqqqa96AOcb41pjgvhfzDij10tkBhIu9m0Jd6tZ1tJB5ZHfHbTffqYVYE0AOGobec/EQ== + dependencies: + "@opentelemetry/core" "1.15.2" + "@opentelemetry/resources" "1.15.2" + "@opentelemetry/semantic-conventions" "1.15.2" + +"@opentelemetry/semantic-conventions@1.15.2", "@opentelemetry/semantic-conventions@^1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.15.2.tgz#3bafb5de3e20e841dff6cb3c66f4d6e9694c4241" + integrity sha512-CjbOKwk2s+3xPIMcd5UNYQzsf+v94RczbdNix9/kQh38WiQkM90sUOi3if8eyHFgiBjBjhwXrA7W3ydiSQP9mw== "@tootallnate/once@2": version "2.0.0" @@ -299,15 +381,30 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-18.15.13.tgz#f64277c341150c979e42b00e4ac289290c9df469" integrity sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q== -"@vscode/extension-telemetry@0.7.5": - version "0.7.5" - resolved "https://registry.yarnpkg.com/@vscode/extension-telemetry/-/extension-telemetry-0.7.5.tgz#bf965731816e08c3f146f96d901ec67954fc913b" - integrity sha512-fJ5y3TcpqqkFYHneabYaoB4XAhDdVflVm+TDKshw9VOs77jkgNS4UA7LNXrWeO0eDne3Sh3JgURf+xzc1rk69w== +"@types/shimmer@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@types/shimmer/-/shimmer-1.0.2.tgz#93eb2c243c351f3f17d5c580c7467ae5d686b65f" + integrity sha512-dKkr1bTxbEsFlh2ARpKzcaAmsYixqt9UyCdoEZk8rHyE4iQYcDCyvSjDSf7JUWJHlJiTtbIoQjxKh6ViywqDAg== + +"@vscode/extension-telemetry@^0.8.4": + version "0.8.4" + resolved "https://registry.yarnpkg.com/@vscode/extension-telemetry/-/extension-telemetry-0.8.4.tgz#c078c6f55df1c9e0592de3b4ce0f685dd345bfe7" + integrity sha512-UqM9+KZDDK3MyoHTsg6XNM+XO6pweQxzCpqJz33BoBEYAGsbBviRYcVpJglgay2oReuDD2pOI1Nio3BKNDLhWA== dependencies: - "@microsoft/1ds-core-js" "^3.2.8" - "@microsoft/1ds-post-js" "^3.2.8" - "@microsoft/applicationinsights-web-basic" "^2.8.9" - applicationinsights "2.4.1" + "@microsoft/1ds-core-js" "^3.2.13" + "@microsoft/1ds-post-js" "^3.2.13" + "@microsoft/applicationinsights-web-basic" "^3.0.2" + applicationinsights "^2.7.1" + +acorn-import-assertions@^1.9.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz#507276249d684797c84e0734ef84860334cfb1ac" + integrity sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA== + +acorn@^8.8.2: + version "8.10.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5" + integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw== agent-base@6: version "6.0.2" @@ -316,22 +413,24 @@ agent-base@6: dependencies: debug "4" -applicationinsights@2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/applicationinsights/-/applicationinsights-2.4.1.tgz#4de4c4dd3c7c4a44445cfbf3d15808fc0dcc423d" - integrity sha512-0n0Ikd0gzSm460xm+M0UTWIwXrhrH/0bqfZatcJjYObWyefxfAxapGEyNnSGd1Tg90neHz+Yhf+Ff/zgvPiQYA== +applicationinsights@^2.7.1: + version "2.7.3" + resolved "https://registry.yarnpkg.com/applicationinsights/-/applicationinsights-2.7.3.tgz#8781454d29c0b14c9773f2e892b4cf5e7468ffa5" + integrity sha512-JY8+kTEkjbA+kAVNWDtpfW2lqsrDALfDXuxOs74KLPu2y13fy/9WB52V4LfYVTVcW1/jYOXjTxNS2gPZIDh1iw== dependencies: - "@azure/core-auth" "^1.4.0" - "@azure/core-rest-pipeline" "^1.10.0" + "@azure/core-auth" "^1.5.0" + "@azure/core-rest-pipeline" "1.10.1" + "@azure/core-util" "1.2.0" + "@azure/opentelemetry-instrumentation-azure-sdk" "^1.0.0-beta.5" "@microsoft/applicationinsights-web-snippet" "^1.0.1" - "@opentelemetry/api" "^1.0.4" - "@opentelemetry/core" "^1.0.1" - "@opentelemetry/sdk-trace-base" "^1.0.1" - "@opentelemetry/semantic-conventions" "^1.0.1" + "@opentelemetry/api" "^1.4.1" + "@opentelemetry/core" "^1.15.2" + "@opentelemetry/sdk-trace-base" "^1.15.2" + "@opentelemetry/semantic-conventions" "^1.15.2" cls-hooked "^4.2.2" continuation-local-storage "^3.2.1" - diagnostic-channel "1.1.0" - diagnostic-channel-publishers "1.0.5" + diagnostic-channel "1.1.1" + diagnostic-channel-publishers "1.0.7" async-hook-jl@^1.7.6: version "1.7.6" @@ -358,6 +457,11 @@ before-after-hook@^2.2.0: resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-2.2.2.tgz#a6e8ca41028d90ee2c24222f201c90956091613e" integrity sha512-3pZEU3NT5BFUo/AD5ERPWOgQOCZITni6iavr5AUw5AUwQjMlI0kzu5btnyD39AF0gUEsDPwJT+oY1ORBJijPjQ== +cjs-module-lexer@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz#6c370ab19f8a3394e318fe682686ec0ac684d107" + integrity sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ== + cls-hooked@^4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/cls-hooked/-/cls-hooked-4.2.2.tgz#ad2e9a4092680cdaffeb2d3551da0e225eae1908" @@ -382,7 +486,7 @@ continuation-local-storage@^3.2.1: async-listener "^0.6.0" emitter-listener "^1.1.1" -debug@4: +debug@4, debug@^4.1.1: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== @@ -399,17 +503,17 @@ deprecation@^2.0.0, deprecation@^2.3.1: resolved "https://registry.yarnpkg.com/deprecation/-/deprecation-2.3.1.tgz#6368cbdb40abf3373b525ac87e4a260c3a700919" integrity sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ== -diagnostic-channel-publishers@1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/diagnostic-channel-publishers/-/diagnostic-channel-publishers-1.0.5.tgz#df8c317086c50f5727fdfb5d2fce214d2e4130ae" - integrity sha512-dJwUS0915pkjjimPJVDnS/QQHsH0aOYhnZsLJdnZIMOrB+csj8RnZhWTuwnm8R5v3Z7OZs+ksv5luC14DGB7eg== +diagnostic-channel-publishers@1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/diagnostic-channel-publishers/-/diagnostic-channel-publishers-1.0.7.tgz#9b7f8d5ee1295481aee19c827d917e96fedf2c4a" + integrity sha512-SEECbY5AiVt6DfLkhkaHNeshg1CogdLLANA8xlG/TKvS+XUgvIKl7VspJGYiEdL5OUyzMVnr7o0AwB7f+/Mjtg== -diagnostic-channel@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/diagnostic-channel/-/diagnostic-channel-1.1.0.tgz#6985e9dfedfbc072d91dc4388477e4087147756e" - integrity sha512-fwujyMe1gj6rk6dYi9hMZm0c8Mz8NDMVl2LB4iaYh3+LIAThZC8RKFGXWG0IML2OxAit/ZFRgZhMkhQ3d/bobQ== +diagnostic-channel@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/diagnostic-channel/-/diagnostic-channel-1.1.1.tgz#44b60972de9ee055c16216535b0e9db3f6a0efd0" + integrity sha512-r2HV5qFkUICyoaKlBEpLKHjxMXATUf/l+h8UZPGBHGLy4DDiY2sOLcIctax4eRnTw5wH2jTMExLntGPJ8eOJxw== dependencies: - semver "^5.3.0" + semver "^7.5.3" emitter-listener@^1.0.1, emitter-listener@^1.1.1: version "1.1.2" @@ -427,6 +531,11 @@ form-data@^4.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + graphql-tag@^2.10.3: version "2.12.6" resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.12.6.tgz#d441a569c1d2537ef10ca3d1633b48725329b5f1" @@ -439,6 +548,13 @@ graphql@^16.0.0: resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.6.0.tgz#c2dcffa4649db149f6282af726c8c83f1c7c5fdb" integrity sha512-KPIBPDlW7NxrbT/eh4qPXz5FiFdL5UbaA0XUNz2Rp3Z3hqBSkbj0GVjwFDztsWVauZUWsbKHgMg++sk8UX0bkw== +has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + http-proxy-agent@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz#5129800203520d434f142bc78ff3c170800f2b43" @@ -456,11 +572,35 @@ https-proxy-agent@^5.0.0: agent-base "6" debug "4" +import-in-the-middle@1.4.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/import-in-the-middle/-/import-in-the-middle-1.4.2.tgz#2a266676e3495e72c04bbaa5ec14756ba168391b" + integrity sha512-9WOz1Yh/cvO/p69sxRmhyQwrIGGSp7EIdcb+fFNVi7CzQGQB8U1/1XrKVSbEd/GNOAeM0peJtmi7+qphe7NvAw== + dependencies: + acorn "^8.8.2" + acorn-import-assertions "^1.9.0" + cjs-module-lexer "^1.2.2" + module-details-from-path "^1.0.3" + +is-core-module@^2.13.0: + version "2.13.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.0.tgz#bb52aa6e2cbd49a30c2ba68c42bf3435ba6072db" + integrity sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ== + dependencies: + has "^1.0.3" + is-plain-object@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344" integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q== +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + mime-db@1.52.0: version "1.52.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" @@ -473,6 +613,11 @@ mime-types@^2.1.12: dependencies: mime-db "1.52.0" +module-details-from-path@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/module-details-from-path/-/module-details-from-path-1.0.3.tgz#114c949673e2a8a35e9d35788527aa37b679da2b" + integrity sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A== + ms@2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" @@ -492,12 +637,42 @@ once@^1.4.0: dependencies: wrappy "1" +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +require-in-the-middle@^7.1.1: + version "7.2.0" + resolved "https://registry.yarnpkg.com/require-in-the-middle/-/require-in-the-middle-7.2.0.tgz#b539de8f00955444dc8aed95e17c69b0a4f10fcf" + integrity sha512-3TLx5TGyAY6AOqLBoXmHkNql0HIf2RGbuMgCDT2WO/uGVAPJs6h7Kl+bN6TIZGd9bWhWPwnDnTHGtW8Iu77sdw== + dependencies: + debug "^4.1.1" + module-details-from-path "^1.0.3" + resolve "^1.22.1" + +resolve@^1.22.1: + version "1.22.4" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.4.tgz#1dc40df46554cdaf8948a486a10f6ba1e2026c34" + integrity sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg== + dependencies: + is-core-module "^2.13.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + semver@^5.3.0, semver@^5.4.1: version "5.7.2" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== -shimmer@^1.1.0, shimmer@^1.2.0: +semver@^7.5.1, semver@^7.5.3: + version "7.5.4" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" + integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== + dependencies: + lru-cache "^6.0.0" + +shimmer@^1.1.0, shimmer@^1.2.0, shimmer@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/shimmer/-/shimmer-1.2.1.tgz#610859f7de327b587efebf501fb43117f9aff337" integrity sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw== @@ -507,6 +682,11 @@ stack-chain@^1.3.7: resolved "https://registry.yarnpkg.com/stack-chain/-/stack-chain-1.3.7.tgz#d192c9ff4ea6a22c94c4dd459171e3f00cea1285" integrity sha512-D8cWtWVdIe/jBA7v5p5Hwl5yOSOrmZPWDPe2KxQ5UAGD+nxbxU0lKXA4h85Ta6+qgdKVL3vUxsbIZjc1kBG7ug== +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + tr46@~0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" @@ -532,6 +712,11 @@ universal-user-agent@^6.0.0: resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-6.0.0.tgz#3381f8503b251c0d9cd21bc1de939ec9df5480ee" integrity sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w== +uuid@^8.3.0: + version "8.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" + integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== + webidl-conversions@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" @@ -549,3 +734,8 @@ wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== diff --git a/extensions/markdown-language-features/package.json b/extensions/markdown-language-features/package.json index 78c71ce9138..9743845b8d9 100644 --- a/extensions/markdown-language-features/package.json +++ b/extensions/markdown-language-features/package.json @@ -726,7 +726,7 @@ "watch-web": "npx webpack-cli --config extension-browser.webpack.config --mode none --watch --info-verbosity verbose" }, "dependencies": { - "@vscode/extension-telemetry": "0.7.5", + "@vscode/extension-telemetry": "^0.8.4", "dompurify": "^3.0.5", "highlight.js": "^11.8.0", "markdown-it": "^12.3.2", diff --git a/extensions/markdown-language-features/yarn.lock b/extensions/markdown-language-features/yarn.lock index 8a47f870e93..36b5aebfed8 100644 --- a/extensions/markdown-language-features/yarn.lock +++ b/extensions/markdown-language-features/yarn.lock @@ -17,7 +17,16 @@ "@azure/abort-controller" "^1.0.0" tslib "^2.2.0" -"@azure/core-rest-pipeline@^1.10.0": +"@azure/core-auth@^1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@azure/core-auth/-/core-auth-1.5.0.tgz#a41848c5c31cb3b7c84c409885267d55a2c92e44" + integrity sha512-udzoBuYG1VBoHVohDTrvKjyzel34zt77Bhp7dQntVGGD0ehVq48owENbBG8fIgkHRNUBQH5k1r0hpoMu5L8+kw== + dependencies: + "@azure/abort-controller" "^1.0.0" + "@azure/core-util" "^1.1.0" + tslib "^2.2.0" + +"@azure/core-rest-pipeline@1.10.1": version "1.10.1" resolved "https://registry.yarnpkg.com/@azure/core-rest-pipeline/-/core-rest-pipeline-1.10.1.tgz#348290847ca31b9eecf9cf5de7519aaccdd30968" integrity sha512-Kji9k6TOFRDB5ZMTw8qUf2IJ+CeJtsuMdAHox9eqpTf1cefiNMpzrfnF6sINEBZJsaVaWgQ0o48B6kcUH68niA== @@ -33,13 +42,21 @@ tslib "^2.2.0" uuid "^8.3.0" -"@azure/core-tracing@^1.0.1": +"@azure/core-tracing@^1.0.0", "@azure/core-tracing@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@azure/core-tracing/-/core-tracing-1.0.1.tgz#352a38cbea438c4a83c86b314f48017d70ba9503" integrity sha512-I5CGMoLtX+pI17ZdiFJZgxMJApsK6jjfm85hpgp3oazCdq5Wxgh4wMr7ge/TTWW1B5WBuvIOI1fMU/FrOAMKrw== dependencies: tslib "^2.2.0" +"@azure/core-util@1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@azure/core-util/-/core-util-1.2.0.tgz#3499deba1fc36dda6f1912b791809b6f15d4a392" + integrity sha512-ffGIw+Qs8bNKNLxz5UPkz4/VBM/EZY07mPve1ZYFqYUdPwFqRj0RPk0U7LZMOfT7GCck9YjuT1Rfp1PApNl1ng== + dependencies: + "@azure/abort-controller" "^1.0.0" + tslib "^2.2.0" + "@azure/core-util@^1.0.0": version "1.1.1" resolved "https://registry.yarnpkg.com/@azure/core-util/-/core-util-1.1.1.tgz#8f87b3dd468795df0f0849d9f096c3e7b29452c1" @@ -48,6 +65,14 @@ "@azure/abort-controller" "^1.0.0" tslib "^2.2.0" +"@azure/core-util@^1.1.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@azure/core-util/-/core-util-1.4.0.tgz#c120a56b3e48a9e4d20619a0b00268ae9de891c7" + integrity sha512-eGAyJpm3skVQoLiRqm/xPa+SXi/NPDdSHMxbRAz2lSprd+Zs+qrpQGQQ2VQ3Nttu+nSZR4XoYQC71LbEI7jsig== + dependencies: + "@azure/abort-controller" "^1.0.0" + tslib "^2.2.0" + "@azure/logger@^1.0.0": version "1.0.3" resolved "https://registry.yarnpkg.com/@azure/logger/-/logger-1.0.3.tgz#6e36704aa51be7d4a1bae24731ea580836293c96" @@ -55,66 +80,100 @@ dependencies: tslib "^2.2.0" -"@microsoft/1ds-core-js@3.2.8", "@microsoft/1ds-core-js@^3.2.8": - version "3.2.8" - resolved "https://registry.yarnpkg.com/@microsoft/1ds-core-js/-/1ds-core-js-3.2.8.tgz#1b6b7d9bb858238c818ccf4e4b58ece7aeae5760" - integrity sha512-9o9SUAamJiTXIYwpkQDuueYt83uZfXp8zp8YFix1IwVPwC9RmE36T2CX9gXOeq1nDckOuOduYpA8qHvdh5BGfQ== +"@azure/opentelemetry-instrumentation-azure-sdk@^1.0.0-beta.5": + version "1.0.0-beta.5" + resolved "https://registry.yarnpkg.com/@azure/opentelemetry-instrumentation-azure-sdk/-/opentelemetry-instrumentation-azure-sdk-1.0.0-beta.5.tgz#78809e6c005d08450701e5d37f087f6fce2f86eb" + integrity sha512-fsUarKQDvjhmBO4nIfaZkfNSApm1hZBzcvpNbSrXdcUBxu7lRvKsV5DnwszX7cnhLyVOW9yl1uigtRQ1yDANjA== dependencies: - "@microsoft/applicationinsights-core-js" "2.8.9" + "@azure/core-tracing" "^1.0.0" + "@azure/logger" "^1.0.0" + "@opentelemetry/api" "^1.4.1" + "@opentelemetry/core" "^1.15.2" + "@opentelemetry/instrumentation" "^0.41.2" + tslib "^2.2.0" + +"@microsoft/1ds-core-js@3.2.13", "@microsoft/1ds-core-js@^3.2.13": + version "3.2.13" + resolved "https://registry.yarnpkg.com/@microsoft/1ds-core-js/-/1ds-core-js-3.2.13.tgz#0c105ed75091bae3f1555c0334704fa9911c58fb" + integrity sha512-CluYTRWcEk0ObG5EWFNWhs87e2qchJUn0p2D21ZUa3PWojPZfPSBs4//WIE0MYV8Qg1Hdif2ZTwlM7TbYUjfAg== + dependencies: + "@microsoft/applicationinsights-core-js" "2.8.15" "@microsoft/applicationinsights-shims" "^2.0.2" "@microsoft/dynamicproto-js" "^1.1.7" -"@microsoft/1ds-post-js@^3.2.8": - version "3.2.8" - resolved "https://registry.yarnpkg.com/@microsoft/1ds-post-js/-/1ds-post-js-3.2.8.tgz#46793842cca161bf7a2a5b6053c349f429e55110" - integrity sha512-SjlRoNcXcXBH6WQD/5SkkaCHIVqldH3gDu+bI7YagrOVJ5APxwT1Duw9gm3L1FjFa9S2i81fvJ3EVSKpp9wULA== +"@microsoft/1ds-post-js@^3.2.13": + version "3.2.13" + resolved "https://registry.yarnpkg.com/@microsoft/1ds-post-js/-/1ds-post-js-3.2.13.tgz#560aacac8a92fdbb79e8c2ebcb293d56e19f51aa" + integrity sha512-HgS574fdD19Bo2vPguyznL4eDw7Pcm1cVNpvbvBLWiW3x4e1FCQ3VMXChWnAxCae8Hb0XqlA2sz332ZobBavTA== dependencies: - "@microsoft/1ds-core-js" "3.2.8" + "@microsoft/1ds-core-js" "3.2.13" "@microsoft/applicationinsights-shims" "^2.0.2" "@microsoft/dynamicproto-js" "^1.1.7" -"@microsoft/applicationinsights-channel-js@2.8.9": - version "2.8.9" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-channel-js/-/applicationinsights-channel-js-2.8.9.tgz#840656f3c716de8b3eb0a98c122aa1b92bb8ebfb" - integrity sha512-fMBsAEB7pWtPn43y72q9Xy5E5y55r6gMuDQqRRccccVoQDPXyS57VCj5IdATblctru0C6A8XpL2vRyNmEsu0Vg== +"@microsoft/applicationinsights-channel-js@3.0.2": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-channel-js/-/applicationinsights-channel-js-3.0.2.tgz#be49fbf74831c7b8c97950027c5052ea99d2a8a5" + integrity sha512-jDBNKbCHsJgmpv0CKNhJ/uN9ZphvfGdb93Svk+R4LjO8L3apNNMbDDPxBvXXi0uigRmA1TBcmyBG4IRKjabGhw== dependencies: - "@microsoft/applicationinsights-common" "2.8.9" - "@microsoft/applicationinsights-core-js" "2.8.9" - "@microsoft/applicationinsights-shims" "2.0.2" - "@microsoft/dynamicproto-js" "^1.1.7" + "@microsoft/applicationinsights-common" "3.0.2" + "@microsoft/applicationinsights-core-js" "3.0.2" + "@microsoft/applicationinsights-shims" "3.0.1" + "@microsoft/dynamicproto-js" "^2.0.2" + "@nevware21/ts-async" ">= 0.2.4 < 2.x" + "@nevware21/ts-utils" ">= 0.9.5 < 2.x" -"@microsoft/applicationinsights-common@2.8.9": - version "2.8.9" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-common/-/applicationinsights-common-2.8.9.tgz#a75e4a3143a7fd797687830c0ddd2069fd900827" - integrity sha512-mObn1moElyxZaGIRF/IU3cOaeKMgxghXnYEoHNUCA2e+rNwBIgxjyKkblFIpmGuHf4X7Oz3o3yBWpaC6AoMpig== +"@microsoft/applicationinsights-common@3.0.2": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-common/-/applicationinsights-common-3.0.2.tgz#37670bb07f4858ed41ff9759119e0759007d6e05" + integrity sha512-y+WXWop+OVim954Cu1uyYMnNx6PWO8okHpZIQi/1YSqtqaYdtJVPv4P0AVzwJdohxzVfgzKvqj9nec/VWqE2Zg== dependencies: - "@microsoft/applicationinsights-core-js" "2.8.9" - "@microsoft/applicationinsights-shims" "2.0.2" - "@microsoft/dynamicproto-js" "^1.1.7" + "@microsoft/applicationinsights-core-js" "3.0.2" + "@microsoft/applicationinsights-shims" "3.0.1" + "@microsoft/dynamicproto-js" "^2.0.2" + "@nevware21/ts-utils" ">= 0.9.5 < 2.x" -"@microsoft/applicationinsights-core-js@2.8.9": - version "2.8.9" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-2.8.9.tgz#0e5d207acfae6986a6fc97249eeb6117e523bf1b" - integrity sha512-HRuIuZ6aOWezcg/G5VyFDDWGL8hDNe/ljPP01J7ImH2kRPEgbtcfPSUMjkamGMefgdq81GZsSoC/NNGTP4pp2w== +"@microsoft/applicationinsights-core-js@2.8.15": + version "2.8.15" + resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-2.8.15.tgz#8fa466474260e01967fe649f14dd9e5ff91dcdc8" + integrity sha512-yYAs9MyjGr2YijQdUSN9mVgT1ijI1FPMgcffpaPmYbHAVbQmF7bXudrBWHxmLzJlwl5rfep+Zgjli2e67lwUqQ== dependencies: "@microsoft/applicationinsights-shims" "2.0.2" - "@microsoft/dynamicproto-js" "^1.1.7" + "@microsoft/dynamicproto-js" "^1.1.9" + +"@microsoft/applicationinsights-core-js@3.0.2": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-3.0.2.tgz#108e20df8c162bec92b1f66f9de2530a25d9f51a" + integrity sha512-WQhVhzlRlLDrQzn3OShCW/pL3BW5WC57t0oywSknX3q7lMzI3jDg7Ihh0iuIcNTzGCTbDkuqr4d6IjEDWIMtJQ== + dependencies: + "@microsoft/applicationinsights-shims" "3.0.1" + "@microsoft/dynamicproto-js" "^2.0.2" + "@nevware21/ts-async" ">= 0.2.4 < 2.x" + "@nevware21/ts-utils" ">= 0.9.5 < 2.x" "@microsoft/applicationinsights-shims@2.0.2", "@microsoft/applicationinsights-shims@^2.0.2": version "2.0.2" resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-shims/-/applicationinsights-shims-2.0.2.tgz#92b36a09375e2d9cb2b4203383b05772be837085" integrity sha512-PoHEgsnmcqruLNHZ/amACqdJ6YYQpED0KSRe6J7gIJTtpZC1FfFU9b1fmDKDKtFoUSrPzEh1qzO3kmRZP0betg== -"@microsoft/applicationinsights-web-basic@^2.8.9": - version "2.8.9" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-web-basic/-/applicationinsights-web-basic-2.8.9.tgz#eed2f3d1e19069962ed2155915c1656e6936e1d5" - integrity sha512-CH0J8JFOy7MjK8JO4pXXU+EML+Ilix+94PMZTX5EJlBU1in+mrik74/8qSg3UC4ekPi12KwrXaHCQSVC3WseXQ== +"@microsoft/applicationinsights-shims@3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-shims/-/applicationinsights-shims-3.0.1.tgz#3865b73ace8405b9c4618cc5c571f2fe3876f06f" + integrity sha512-DKwboF47H1nb33rSUfjqI6ryX29v+2QWcTrRvcQDA32AZr5Ilkr7whOOSsD1aBzwqX0RJEIP1Z81jfE3NBm/Lg== dependencies: - "@microsoft/applicationinsights-channel-js" "2.8.9" - "@microsoft/applicationinsights-common" "2.8.9" - "@microsoft/applicationinsights-core-js" "2.8.9" - "@microsoft/applicationinsights-shims" "2.0.2" - "@microsoft/dynamicproto-js" "^1.1.7" + "@nevware21/ts-utils" ">= 0.9.4 < 2.x" + +"@microsoft/applicationinsights-web-basic@^3.0.2": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-web-basic/-/applicationinsights-web-basic-3.0.2.tgz#f777a4d24b79dde3ae396d3b819e1fce06b7240a" + integrity sha512-6Lq0DE/pZp9RvSV+weGbcxN1NDmfczj6gNPhvZKV2YSQ3RK0LZE3+wjTWLXfuStq8a+nCBdsRpWk8tOKgsoxcg== + dependencies: + "@microsoft/applicationinsights-channel-js" "3.0.2" + "@microsoft/applicationinsights-common" "3.0.2" + "@microsoft/applicationinsights-core-js" "3.0.2" + "@microsoft/applicationinsights-shims" "3.0.1" + "@microsoft/dynamicproto-js" "^2.0.2" + "@nevware21/ts-async" ">= 0.2.4 < 2.x" + "@nevware21/ts-utils" ">= 0.9.5 < 2.x" "@microsoft/applicationinsights-web-snippet@^1.0.1": version "1.0.1" @@ -126,39 +185,74 @@ resolved "https://registry.yarnpkg.com/@microsoft/dynamicproto-js/-/dynamicproto-js-1.1.7.tgz#ede48dd3f85af14ee369c805e5ed5b84222b9fe2" integrity sha512-SK3D3aVt+5vOOccKPnGaJWB5gQ8FuKfjboUJHedMP7gu54HqSCXX5iFXhktGD8nfJb0Go30eDvs/UDoTnR2kOA== -"@opentelemetry/api@^1.0.4": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.2.0.tgz#89ef99401cde6208cff98760b67663726ef26686" - integrity sha512-0nBr+VZNKm9tvNDZFstI3Pq1fCTEDK5OZTnVKNvBNAKgd0yIvmwsP4m61rEv7ZP+tOUjWJhROpxK5MsnlF911g== +"@microsoft/dynamicproto-js@^1.1.9": + version "1.1.9" + resolved "https://registry.yarnpkg.com/@microsoft/dynamicproto-js/-/dynamicproto-js-1.1.9.tgz#7437db7aa061162ee94e4131b69a62b8dad5dea6" + integrity sha512-n1VPsljTSkthsAFYdiWfC+DKzK2WwcRp83Y1YAqdX552BstvsDjft9YXppjUzp11BPsapDoO1LDgrDB0XVsfNQ== -"@opentelemetry/core@1.7.0", "@opentelemetry/core@^1.0.1": - version "1.7.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-1.7.0.tgz#83bdd1b7a4ceafcdffd6590420657caec5f7b34c" - integrity sha512-AVqAi5uc8DrKJBimCTFUT4iFI+5eXpo4sYmGbQ0CypG0piOTHE2g9c5aSoTGYXu3CzOmJZf7pT6Xh+nwm5d6yQ== +"@microsoft/dynamicproto-js@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@microsoft/dynamicproto-js/-/dynamicproto-js-2.0.2.tgz#e57fbec2e7067d48b7e8e1e1c1d354028ef718a6" + integrity sha512-MB8trWaFREpmb037k/d0bB7T2BP7Ai24w1e1tbz3ASLB0/lwphsq3Nq8S9I5AsI5vs4zAQT+SB5nC5/dLYTiOg== dependencies: - "@opentelemetry/semantic-conventions" "1.7.0" + "@nevware21/ts-utils" ">= 0.9.4 < 2.x" -"@opentelemetry/resources@1.7.0": - version "1.7.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/resources/-/resources-1.7.0.tgz#90ccd3a6a86b4dfba4e833e73944bd64958d78c5" - integrity sha512-u1M0yZotkjyKx8dj+46Sg5thwtOTBmtRieNXqdCRiWUp6SfFiIP0bI+1XK3LhuXqXkBXA1awJZaTqKduNMStRg== +"@nevware21/ts-async@>= 0.2.4 < 2.x": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@nevware21/ts-async/-/ts-async-0.3.0.tgz#a8b97ba01065fc930de9a3f4dd4a05e862becc6c" + integrity sha512-ZUcgUH12LN/F6nzN0cYd0F/rJaMLmXr0EHVTyYfaYmK55bdwE4338uue4UiVoRqHVqNW4KDUrJc49iGogHKeWA== dependencies: - "@opentelemetry/core" "1.7.0" - "@opentelemetry/semantic-conventions" "1.7.0" + "@nevware21/ts-utils" ">= 0.10.0 < 2.x" -"@opentelemetry/sdk-trace-base@^1.0.1": - version "1.7.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.7.0.tgz#b498424e0c6340a9d80de63fd408c5c2130a60a5" - integrity sha512-Iz84C+FVOskmauh9FNnj4+VrA+hG5o+tkMzXuoesvSfunVSioXib0syVFeNXwOm4+M5GdWCuW632LVjqEXStIg== +"@nevware21/ts-utils@>= 0.10.0 < 2.x", "@nevware21/ts-utils@>= 0.9.4 < 2.x", "@nevware21/ts-utils@>= 0.9.5 < 2.x": + version "0.10.1" + resolved "https://registry.yarnpkg.com/@nevware21/ts-utils/-/ts-utils-0.10.1.tgz#aa65abc71eba06749a396598f22263d26f796ac7" + integrity sha512-pMny25NnF2/MJwdqC3Iyjm2pGIXNxni4AROpcqDeWa+td9JMUY4bUS9uU9XW+BoBRqTLUL+WURF9SOd/6OQzRg== + +"@opentelemetry/api@^1.4.1": + version "1.4.1" + resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.4.1.tgz#ff22eb2e5d476fbc2450a196e40dd243cc20c28f" + integrity sha512-O2yRJce1GOc6PAy3QxFM4NzFiWzvScDC1/5ihYBL6BUEVdq0XMWN01sppE+H6bBXbaFYipjwFLEWLg5PaSOThA== + +"@opentelemetry/core@1.15.2", "@opentelemetry/core@^1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-1.15.2.tgz#5b170bf223a2333884bbc2d29d95812cdbda7c9f" + integrity sha512-+gBv15ta96WqkHZaPpcDHiaz0utiiHZVfm2YOYSqFGrUaJpPkMoSuLBB58YFQGi6Rsb9EHos84X6X5+9JspmLw== dependencies: - "@opentelemetry/core" "1.7.0" - "@opentelemetry/resources" "1.7.0" - "@opentelemetry/semantic-conventions" "1.7.0" + "@opentelemetry/semantic-conventions" "1.15.2" -"@opentelemetry/semantic-conventions@1.7.0", "@opentelemetry/semantic-conventions@^1.0.1": - version "1.7.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.7.0.tgz#af80a1ef7cf110ea3a68242acd95648991bcd763" - integrity sha512-FGBx/Qd09lMaqQcogCHyYrFEpTx4cAjeS+48lMIR12z7LdH+zofGDVQSubN59nL6IpubfKqTeIDu9rNO28iHVA== +"@opentelemetry/instrumentation@^0.41.2": + version "0.41.2" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation/-/instrumentation-0.41.2.tgz#cae11fa64485dcf03dae331f35b315b64bc6189f" + integrity sha512-rxU72E0pKNH6ae2w5+xgVYZLzc5mlxAbGzF4shxMVK8YC2QQsfN38B2GPbj0jvrKWWNUElfclQ+YTykkNg/grw== + dependencies: + "@types/shimmer" "^1.0.2" + import-in-the-middle "1.4.2" + require-in-the-middle "^7.1.1" + semver "^7.5.1" + shimmer "^1.2.1" + +"@opentelemetry/resources@1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@opentelemetry/resources/-/resources-1.15.2.tgz#0c9e26cb65652a1402834a3c030cce6028d6dd9d" + integrity sha512-xmMRLenT9CXmm5HMbzpZ1hWhaUowQf8UB4jMjFlAxx1QzQcsD3KFNAVX/CAWzFPtllTyTplrA4JrQ7sCH3qmYw== + dependencies: + "@opentelemetry/core" "1.15.2" + "@opentelemetry/semantic-conventions" "1.15.2" + +"@opentelemetry/sdk-trace-base@^1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.15.2.tgz#4821f94033c55a6c8bbd35ae387b715b6108517a" + integrity sha512-BEaxGZbWtvnSPchV98qqqqa96AOcb41pjgvhfzDij10tkBhIu9m0Jd6tZ1tJB5ZHfHbTffqYVYE0AOGobec/EQ== + dependencies: + "@opentelemetry/core" "1.15.2" + "@opentelemetry/resources" "1.15.2" + "@opentelemetry/semantic-conventions" "1.15.2" + +"@opentelemetry/semantic-conventions@1.15.2", "@opentelemetry/semantic-conventions@^1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.15.2.tgz#3bafb5de3e20e841dff6cb3c66f4d6e9694c4241" + integrity sha512-CjbOKwk2s+3xPIMcd5UNYQzsf+v94RczbdNix9/kQh38WiQkM90sUOi3if8eyHFgiBjBjhwXrA7W3ydiSQP9mw== "@tootallnate/once@2": version "2.0.0" @@ -207,6 +301,11 @@ resolved "https://registry.yarnpkg.com/@types/picomatch/-/picomatch-2.3.0.tgz#75db5e75a713c5a83d5b76780c3da84a82806003" integrity sha512-O397rnSS9iQI4OirieAtsDqvCj4+3eY1J+EPdNTKuHuRWIfUoGyzX294o8C4KJYaLqgSrd2o60c5EqCU8Zv02g== +"@types/shimmer@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@types/shimmer/-/shimmer-1.0.2.tgz#93eb2c243c351f3f17d5c580c7467ae5d686b65f" + integrity sha512-dKkr1bTxbEsFlh2ARpKzcaAmsYixqt9UyCdoEZk8rHyE4iQYcDCyvSjDSf7JUWJHlJiTtbIoQjxKh6ViywqDAg== + "@types/trusted-types@*": version "2.0.2" resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.2.tgz#fc25ad9943bcac11cceb8168db4f275e0e72e756" @@ -222,21 +321,31 @@ resolved "https://registry.yarnpkg.com/@types/vscode-webview/-/vscode-webview-1.57.0.tgz#bad5194d45ae8d03afc1c0f67f71ff5e7a243bbf" integrity sha512-x3Cb/SMa1IwRHfSvKaZDZOTh4cNoG505c3NjTqGlMC082m++x/ETUmtYniDsw6SSmYzZXO8KBNhYxR0+VqymqA== -"@vscode/extension-telemetry@0.7.5": - version "0.7.5" - resolved "https://registry.yarnpkg.com/@vscode/extension-telemetry/-/extension-telemetry-0.7.5.tgz#bf965731816e08c3f146f96d901ec67954fc913b" - integrity sha512-fJ5y3TcpqqkFYHneabYaoB4XAhDdVflVm+TDKshw9VOs77jkgNS4UA7LNXrWeO0eDne3Sh3JgURf+xzc1rk69w== +"@vscode/extension-telemetry@^0.8.4": + version "0.8.4" + resolved "https://registry.yarnpkg.com/@vscode/extension-telemetry/-/extension-telemetry-0.8.4.tgz#c078c6f55df1c9e0592de3b4ce0f685dd345bfe7" + integrity sha512-UqM9+KZDDK3MyoHTsg6XNM+XO6pweQxzCpqJz33BoBEYAGsbBviRYcVpJglgay2oReuDD2pOI1Nio3BKNDLhWA== dependencies: - "@microsoft/1ds-core-js" "^3.2.8" - "@microsoft/1ds-post-js" "^3.2.8" - "@microsoft/applicationinsights-web-basic" "^2.8.9" - applicationinsights "2.4.1" + "@microsoft/1ds-core-js" "^3.2.13" + "@microsoft/1ds-post-js" "^3.2.13" + "@microsoft/applicationinsights-web-basic" "^3.0.2" + applicationinsights "^2.7.1" "@vscode/l10n@^0.0.10": version "0.0.10" resolved "https://registry.yarnpkg.com/@vscode/l10n/-/l10n-0.0.10.tgz#9c513107c690c0dd16e3ec61e453743de15ebdb0" integrity sha512-E1OCmDcDWa0Ya7vtSjp/XfHFGqYJfh+YPC1RkATU71fTac+j1JjCcB3qwSzmlKAighx2WxhLlfhS0RwAN++PFQ== +acorn-import-assertions@^1.9.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz#507276249d684797c84e0734ef84860334cfb1ac" + integrity sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA== + +acorn@^8.8.2: + version "8.10.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5" + integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw== + agent-base@6: version "6.0.2" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" @@ -244,22 +353,24 @@ agent-base@6: dependencies: debug "4" -applicationinsights@2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/applicationinsights/-/applicationinsights-2.4.1.tgz#4de4c4dd3c7c4a44445cfbf3d15808fc0dcc423d" - integrity sha512-0n0Ikd0gzSm460xm+M0UTWIwXrhrH/0bqfZatcJjYObWyefxfAxapGEyNnSGd1Tg90neHz+Yhf+Ff/zgvPiQYA== +applicationinsights@^2.7.1: + version "2.7.3" + resolved "https://registry.yarnpkg.com/applicationinsights/-/applicationinsights-2.7.3.tgz#8781454d29c0b14c9773f2e892b4cf5e7468ffa5" + integrity sha512-JY8+kTEkjbA+kAVNWDtpfW2lqsrDALfDXuxOs74KLPu2y13fy/9WB52V4LfYVTVcW1/jYOXjTxNS2gPZIDh1iw== dependencies: - "@azure/core-auth" "^1.4.0" - "@azure/core-rest-pipeline" "^1.10.0" + "@azure/core-auth" "^1.5.0" + "@azure/core-rest-pipeline" "1.10.1" + "@azure/core-util" "1.2.0" + "@azure/opentelemetry-instrumentation-azure-sdk" "^1.0.0-beta.5" "@microsoft/applicationinsights-web-snippet" "^1.0.1" - "@opentelemetry/api" "^1.0.4" - "@opentelemetry/core" "^1.0.1" - "@opentelemetry/sdk-trace-base" "^1.0.1" - "@opentelemetry/semantic-conventions" "^1.0.1" + "@opentelemetry/api" "^1.4.1" + "@opentelemetry/core" "^1.15.2" + "@opentelemetry/sdk-trace-base" "^1.15.2" + "@opentelemetry/semantic-conventions" "^1.15.2" cls-hooked "^4.2.2" continuation-local-storage "^3.2.1" - diagnostic-channel "1.1.0" - diagnostic-channel-publishers "1.0.5" + diagnostic-channel "1.1.1" + diagnostic-channel-publishers "1.0.7" argparse@^2.0.1: version "2.0.1" @@ -299,6 +410,11 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" +cjs-module-lexer@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz#6c370ab19f8a3394e318fe682686ec0ac684d107" + integrity sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ== + cls-hooked@^4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/cls-hooked/-/cls-hooked-4.2.2.tgz#ad2e9a4092680cdaffeb2d3551da0e225eae1908" @@ -328,7 +444,7 @@ continuation-local-storage@^3.2.1: async-listener "^0.6.0" emitter-listener "^1.1.1" -debug@4: +debug@4, debug@^4.1.1: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== @@ -340,17 +456,17 @@ delayed-stream@~1.0.0: resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== -diagnostic-channel-publishers@1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/diagnostic-channel-publishers/-/diagnostic-channel-publishers-1.0.5.tgz#df8c317086c50f5727fdfb5d2fce214d2e4130ae" - integrity sha512-dJwUS0915pkjjimPJVDnS/QQHsH0aOYhnZsLJdnZIMOrB+csj8RnZhWTuwnm8R5v3Z7OZs+ksv5luC14DGB7eg== +diagnostic-channel-publishers@1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/diagnostic-channel-publishers/-/diagnostic-channel-publishers-1.0.7.tgz#9b7f8d5ee1295481aee19c827d917e96fedf2c4a" + integrity sha512-SEECbY5AiVt6DfLkhkaHNeshg1CogdLLANA8xlG/TKvS+XUgvIKl7VspJGYiEdL5OUyzMVnr7o0AwB7f+/Mjtg== -diagnostic-channel@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/diagnostic-channel/-/diagnostic-channel-1.1.0.tgz#6985e9dfedfbc072d91dc4388477e4087147756e" - integrity sha512-fwujyMe1gj6rk6dYi9hMZm0c8Mz8NDMVl2LB4iaYh3+LIAThZC8RKFGXWG0IML2OxAit/ZFRgZhMkhQ3d/bobQ== +diagnostic-channel@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/diagnostic-channel/-/diagnostic-channel-1.1.1.tgz#44b60972de9ee055c16216535b0e9db3f6a0efd0" + integrity sha512-r2HV5qFkUICyoaKlBEpLKHjxMXATUf/l+h8UZPGBHGLy4DDiY2sOLcIctax4eRnTw5wH2jTMExLntGPJ8eOJxw== dependencies: - semver "^5.3.0" + semver "^7.5.3" dompurify@^3.0.5: version "3.0.5" @@ -378,6 +494,18 @@ form-data@^4.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + highlight.js@^11.8.0: version "11.8.0" resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-11.8.0.tgz#966518ea83257bae2e7c9a48596231856555bb65" @@ -400,6 +528,23 @@ https-proxy-agent@^5.0.0: agent-base "6" debug "4" +import-in-the-middle@1.4.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/import-in-the-middle/-/import-in-the-middle-1.4.2.tgz#2a266676e3495e72c04bbaa5ec14756ba168391b" + integrity sha512-9WOz1Yh/cvO/p69sxRmhyQwrIGGSp7EIdcb+fFNVi7CzQGQB8U1/1XrKVSbEd/GNOAeM0peJtmi7+qphe7NvAw== + dependencies: + acorn "^8.8.2" + acorn-import-assertions "^1.9.0" + cjs-module-lexer "^1.2.2" + module-details-from-path "^1.0.3" + +is-core-module@^2.13.0: + version "2.13.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.0.tgz#bb52aa6e2cbd49a30c2ba68c42bf3435ba6072db" + integrity sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ== + dependencies: + has "^1.0.3" + linkify-it@^3.0.1: version "3.0.3" resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-3.0.3.tgz#a98baf44ce45a550efb4d49c769d07524cc2fa2e" @@ -459,6 +604,11 @@ minimatch@^3.0.4: dependencies: brace-expansion "^1.1.7" +module-details-from-path@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/module-details-from-path/-/module-details-from-path-1.0.3.tgz#114c949673e2a8a35e9d35788527aa37b679da2b" + integrity sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A== + morphdom@^2.6.1: version "2.6.1" resolved "https://registry.yarnpkg.com/morphdom/-/morphdom-2.6.1.tgz#e868e24f989fa3183004b159aed643e628b4306e" @@ -469,24 +619,47 @@ ms@2.1.2: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + picomatch@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== +require-in-the-middle@^7.1.1: + version "7.2.0" + resolved "https://registry.yarnpkg.com/require-in-the-middle/-/require-in-the-middle-7.2.0.tgz#b539de8f00955444dc8aed95e17c69b0a4f10fcf" + integrity sha512-3TLx5TGyAY6AOqLBoXmHkNql0HIf2RGbuMgCDT2WO/uGVAPJs6h7Kl+bN6TIZGd9bWhWPwnDnTHGtW8Iu77sdw== + dependencies: + debug "^4.1.1" + module-details-from-path "^1.0.3" + resolve "^1.22.1" + +resolve@^1.22.1: + version "1.22.4" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.4.tgz#1dc40df46554cdaf8948a486a10f6ba1e2026c34" + integrity sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg== + dependencies: + is-core-module "^2.13.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + semver@^5.3.0, semver@^5.4.1: version "5.7.2" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== -semver@^7.3.5: +semver@^7.3.5, semver@^7.5.1, semver@^7.5.3: version "7.5.4" resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== dependencies: lru-cache "^6.0.0" -shimmer@^1.1.0, shimmer@^1.2.0: +shimmer@^1.1.0, shimmer@^1.2.0, shimmer@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/shimmer/-/shimmer-1.2.1.tgz#610859f7de327b587efebf501fb43117f9aff337" integrity sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw== @@ -496,6 +669,11 @@ stack-chain@^1.3.7: resolved "https://registry.yarnpkg.com/stack-chain/-/stack-chain-1.3.7.tgz#d192c9ff4ea6a22c94c4dd459171e3f00cea1285" integrity sha512-D8cWtWVdIe/jBA7v5p5Hwl5yOSOrmZPWDPe2KxQ5UAGD+nxbxU0lKXA4h85Ta6+qgdKVL3vUxsbIZjc1kBG7ug== +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + tslib@^2.2.0: version "2.4.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.1.tgz#0d0bfbaac2880b91e22df0768e55be9753a5b17e" diff --git a/extensions/media-preview/package.json b/extensions/media-preview/package.json index 3107d9d60bf..6c1b46220b9 100644 --- a/extensions/media-preview/package.json +++ b/extensions/media-preview/package.json @@ -126,7 +126,7 @@ "watch-web": "npx webpack-cli --config extension-browser.webpack.config --mode none --watch --info-verbosity verbose" }, "dependencies": { - "@vscode/extension-telemetry": "0.7.5", + "@vscode/extension-telemetry": "^0.8.4", "vscode-uri": "^3.0.6" }, "repository": { diff --git a/extensions/media-preview/yarn.lock b/extensions/media-preview/yarn.lock index 971c4c2c50a..36b652d7d7b 100644 --- a/extensions/media-preview/yarn.lock +++ b/extensions/media-preview/yarn.lock @@ -17,7 +17,16 @@ "@azure/abort-controller" "^1.0.0" tslib "^2.2.0" -"@azure/core-rest-pipeline@^1.10.0": +"@azure/core-auth@^1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@azure/core-auth/-/core-auth-1.5.0.tgz#a41848c5c31cb3b7c84c409885267d55a2c92e44" + integrity sha512-udzoBuYG1VBoHVohDTrvKjyzel34zt77Bhp7dQntVGGD0ehVq48owENbBG8fIgkHRNUBQH5k1r0hpoMu5L8+kw== + dependencies: + "@azure/abort-controller" "^1.0.0" + "@azure/core-util" "^1.1.0" + tslib "^2.2.0" + +"@azure/core-rest-pipeline@1.10.1": version "1.10.1" resolved "https://registry.yarnpkg.com/@azure/core-rest-pipeline/-/core-rest-pipeline-1.10.1.tgz#348290847ca31b9eecf9cf5de7519aaccdd30968" integrity sha512-Kji9k6TOFRDB5ZMTw8qUf2IJ+CeJtsuMdAHox9eqpTf1cefiNMpzrfnF6sINEBZJsaVaWgQ0o48B6kcUH68niA== @@ -33,13 +42,21 @@ tslib "^2.2.0" uuid "^8.3.0" -"@azure/core-tracing@^1.0.1": +"@azure/core-tracing@^1.0.0", "@azure/core-tracing@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@azure/core-tracing/-/core-tracing-1.0.1.tgz#352a38cbea438c4a83c86b314f48017d70ba9503" integrity sha512-I5CGMoLtX+pI17ZdiFJZgxMJApsK6jjfm85hpgp3oazCdq5Wxgh4wMr7ge/TTWW1B5WBuvIOI1fMU/FrOAMKrw== dependencies: tslib "^2.2.0" +"@azure/core-util@1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@azure/core-util/-/core-util-1.2.0.tgz#3499deba1fc36dda6f1912b791809b6f15d4a392" + integrity sha512-ffGIw+Qs8bNKNLxz5UPkz4/VBM/EZY07mPve1ZYFqYUdPwFqRj0RPk0U7LZMOfT7GCck9YjuT1Rfp1PApNl1ng== + dependencies: + "@azure/abort-controller" "^1.0.0" + tslib "^2.2.0" + "@azure/core-util@^1.0.0": version "1.1.1" resolved "https://registry.yarnpkg.com/@azure/core-util/-/core-util-1.1.1.tgz#8f87b3dd468795df0f0849d9f096c3e7b29452c1" @@ -48,6 +65,14 @@ "@azure/abort-controller" "^1.0.0" tslib "^2.2.0" +"@azure/core-util@^1.1.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@azure/core-util/-/core-util-1.4.0.tgz#c120a56b3e48a9e4d20619a0b00268ae9de891c7" + integrity sha512-eGAyJpm3skVQoLiRqm/xPa+SXi/NPDdSHMxbRAz2lSprd+Zs+qrpQGQQ2VQ3Nttu+nSZR4XoYQC71LbEI7jsig== + dependencies: + "@azure/abort-controller" "^1.0.0" + tslib "^2.2.0" + "@azure/logger@^1.0.0": version "1.0.3" resolved "https://registry.yarnpkg.com/@azure/logger/-/logger-1.0.3.tgz#6e36704aa51be7d4a1bae24731ea580836293c96" @@ -55,66 +80,100 @@ dependencies: tslib "^2.2.0" -"@microsoft/1ds-core-js@3.2.8", "@microsoft/1ds-core-js@^3.2.8": - version "3.2.8" - resolved "https://registry.yarnpkg.com/@microsoft/1ds-core-js/-/1ds-core-js-3.2.8.tgz#1b6b7d9bb858238c818ccf4e4b58ece7aeae5760" - integrity sha512-9o9SUAamJiTXIYwpkQDuueYt83uZfXp8zp8YFix1IwVPwC9RmE36T2CX9gXOeq1nDckOuOduYpA8qHvdh5BGfQ== +"@azure/opentelemetry-instrumentation-azure-sdk@^1.0.0-beta.5": + version "1.0.0-beta.5" + resolved "https://registry.yarnpkg.com/@azure/opentelemetry-instrumentation-azure-sdk/-/opentelemetry-instrumentation-azure-sdk-1.0.0-beta.5.tgz#78809e6c005d08450701e5d37f087f6fce2f86eb" + integrity sha512-fsUarKQDvjhmBO4nIfaZkfNSApm1hZBzcvpNbSrXdcUBxu7lRvKsV5DnwszX7cnhLyVOW9yl1uigtRQ1yDANjA== dependencies: - "@microsoft/applicationinsights-core-js" "2.8.9" + "@azure/core-tracing" "^1.0.0" + "@azure/logger" "^1.0.0" + "@opentelemetry/api" "^1.4.1" + "@opentelemetry/core" "^1.15.2" + "@opentelemetry/instrumentation" "^0.41.2" + tslib "^2.2.0" + +"@microsoft/1ds-core-js@3.2.13", "@microsoft/1ds-core-js@^3.2.13": + version "3.2.13" + resolved "https://registry.yarnpkg.com/@microsoft/1ds-core-js/-/1ds-core-js-3.2.13.tgz#0c105ed75091bae3f1555c0334704fa9911c58fb" + integrity sha512-CluYTRWcEk0ObG5EWFNWhs87e2qchJUn0p2D21ZUa3PWojPZfPSBs4//WIE0MYV8Qg1Hdif2ZTwlM7TbYUjfAg== + dependencies: + "@microsoft/applicationinsights-core-js" "2.8.15" "@microsoft/applicationinsights-shims" "^2.0.2" "@microsoft/dynamicproto-js" "^1.1.7" -"@microsoft/1ds-post-js@^3.2.8": - version "3.2.8" - resolved "https://registry.yarnpkg.com/@microsoft/1ds-post-js/-/1ds-post-js-3.2.8.tgz#46793842cca161bf7a2a5b6053c349f429e55110" - integrity sha512-SjlRoNcXcXBH6WQD/5SkkaCHIVqldH3gDu+bI7YagrOVJ5APxwT1Duw9gm3L1FjFa9S2i81fvJ3EVSKpp9wULA== +"@microsoft/1ds-post-js@^3.2.13": + version "3.2.13" + resolved "https://registry.yarnpkg.com/@microsoft/1ds-post-js/-/1ds-post-js-3.2.13.tgz#560aacac8a92fdbb79e8c2ebcb293d56e19f51aa" + integrity sha512-HgS574fdD19Bo2vPguyznL4eDw7Pcm1cVNpvbvBLWiW3x4e1FCQ3VMXChWnAxCae8Hb0XqlA2sz332ZobBavTA== dependencies: - "@microsoft/1ds-core-js" "3.2.8" + "@microsoft/1ds-core-js" "3.2.13" "@microsoft/applicationinsights-shims" "^2.0.2" "@microsoft/dynamicproto-js" "^1.1.7" -"@microsoft/applicationinsights-channel-js@2.8.9": - version "2.8.9" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-channel-js/-/applicationinsights-channel-js-2.8.9.tgz#840656f3c716de8b3eb0a98c122aa1b92bb8ebfb" - integrity sha512-fMBsAEB7pWtPn43y72q9Xy5E5y55r6gMuDQqRRccccVoQDPXyS57VCj5IdATblctru0C6A8XpL2vRyNmEsu0Vg== +"@microsoft/applicationinsights-channel-js@3.0.2": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-channel-js/-/applicationinsights-channel-js-3.0.2.tgz#be49fbf74831c7b8c97950027c5052ea99d2a8a5" + integrity sha512-jDBNKbCHsJgmpv0CKNhJ/uN9ZphvfGdb93Svk+R4LjO8L3apNNMbDDPxBvXXi0uigRmA1TBcmyBG4IRKjabGhw== dependencies: - "@microsoft/applicationinsights-common" "2.8.9" - "@microsoft/applicationinsights-core-js" "2.8.9" - "@microsoft/applicationinsights-shims" "2.0.2" - "@microsoft/dynamicproto-js" "^1.1.7" + "@microsoft/applicationinsights-common" "3.0.2" + "@microsoft/applicationinsights-core-js" "3.0.2" + "@microsoft/applicationinsights-shims" "3.0.1" + "@microsoft/dynamicproto-js" "^2.0.2" + "@nevware21/ts-async" ">= 0.2.4 < 2.x" + "@nevware21/ts-utils" ">= 0.9.5 < 2.x" -"@microsoft/applicationinsights-common@2.8.9": - version "2.8.9" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-common/-/applicationinsights-common-2.8.9.tgz#a75e4a3143a7fd797687830c0ddd2069fd900827" - integrity sha512-mObn1moElyxZaGIRF/IU3cOaeKMgxghXnYEoHNUCA2e+rNwBIgxjyKkblFIpmGuHf4X7Oz3o3yBWpaC6AoMpig== +"@microsoft/applicationinsights-common@3.0.2": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-common/-/applicationinsights-common-3.0.2.tgz#37670bb07f4858ed41ff9759119e0759007d6e05" + integrity sha512-y+WXWop+OVim954Cu1uyYMnNx6PWO8okHpZIQi/1YSqtqaYdtJVPv4P0AVzwJdohxzVfgzKvqj9nec/VWqE2Zg== dependencies: - "@microsoft/applicationinsights-core-js" "2.8.9" - "@microsoft/applicationinsights-shims" "2.0.2" - "@microsoft/dynamicproto-js" "^1.1.7" + "@microsoft/applicationinsights-core-js" "3.0.2" + "@microsoft/applicationinsights-shims" "3.0.1" + "@microsoft/dynamicproto-js" "^2.0.2" + "@nevware21/ts-utils" ">= 0.9.5 < 2.x" -"@microsoft/applicationinsights-core-js@2.8.9": - version "2.8.9" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-2.8.9.tgz#0e5d207acfae6986a6fc97249eeb6117e523bf1b" - integrity sha512-HRuIuZ6aOWezcg/G5VyFDDWGL8hDNe/ljPP01J7ImH2kRPEgbtcfPSUMjkamGMefgdq81GZsSoC/NNGTP4pp2w== +"@microsoft/applicationinsights-core-js@2.8.15": + version "2.8.15" + resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-2.8.15.tgz#8fa466474260e01967fe649f14dd9e5ff91dcdc8" + integrity sha512-yYAs9MyjGr2YijQdUSN9mVgT1ijI1FPMgcffpaPmYbHAVbQmF7bXudrBWHxmLzJlwl5rfep+Zgjli2e67lwUqQ== dependencies: "@microsoft/applicationinsights-shims" "2.0.2" - "@microsoft/dynamicproto-js" "^1.1.7" + "@microsoft/dynamicproto-js" "^1.1.9" + +"@microsoft/applicationinsights-core-js@3.0.2": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-3.0.2.tgz#108e20df8c162bec92b1f66f9de2530a25d9f51a" + integrity sha512-WQhVhzlRlLDrQzn3OShCW/pL3BW5WC57t0oywSknX3q7lMzI3jDg7Ihh0iuIcNTzGCTbDkuqr4d6IjEDWIMtJQ== + dependencies: + "@microsoft/applicationinsights-shims" "3.0.1" + "@microsoft/dynamicproto-js" "^2.0.2" + "@nevware21/ts-async" ">= 0.2.4 < 2.x" + "@nevware21/ts-utils" ">= 0.9.5 < 2.x" "@microsoft/applicationinsights-shims@2.0.2", "@microsoft/applicationinsights-shims@^2.0.2": version "2.0.2" resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-shims/-/applicationinsights-shims-2.0.2.tgz#92b36a09375e2d9cb2b4203383b05772be837085" integrity sha512-PoHEgsnmcqruLNHZ/amACqdJ6YYQpED0KSRe6J7gIJTtpZC1FfFU9b1fmDKDKtFoUSrPzEh1qzO3kmRZP0betg== -"@microsoft/applicationinsights-web-basic@^2.8.9": - version "2.8.9" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-web-basic/-/applicationinsights-web-basic-2.8.9.tgz#eed2f3d1e19069962ed2155915c1656e6936e1d5" - integrity sha512-CH0J8JFOy7MjK8JO4pXXU+EML+Ilix+94PMZTX5EJlBU1in+mrik74/8qSg3UC4ekPi12KwrXaHCQSVC3WseXQ== +"@microsoft/applicationinsights-shims@3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-shims/-/applicationinsights-shims-3.0.1.tgz#3865b73ace8405b9c4618cc5c571f2fe3876f06f" + integrity sha512-DKwboF47H1nb33rSUfjqI6ryX29v+2QWcTrRvcQDA32AZr5Ilkr7whOOSsD1aBzwqX0RJEIP1Z81jfE3NBm/Lg== dependencies: - "@microsoft/applicationinsights-channel-js" "2.8.9" - "@microsoft/applicationinsights-common" "2.8.9" - "@microsoft/applicationinsights-core-js" "2.8.9" - "@microsoft/applicationinsights-shims" "2.0.2" - "@microsoft/dynamicproto-js" "^1.1.7" + "@nevware21/ts-utils" ">= 0.9.4 < 2.x" + +"@microsoft/applicationinsights-web-basic@^3.0.2": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-web-basic/-/applicationinsights-web-basic-3.0.2.tgz#f777a4d24b79dde3ae396d3b819e1fce06b7240a" + integrity sha512-6Lq0DE/pZp9RvSV+weGbcxN1NDmfczj6gNPhvZKV2YSQ3RK0LZE3+wjTWLXfuStq8a+nCBdsRpWk8tOKgsoxcg== + dependencies: + "@microsoft/applicationinsights-channel-js" "3.0.2" + "@microsoft/applicationinsights-common" "3.0.2" + "@microsoft/applicationinsights-core-js" "3.0.2" + "@microsoft/applicationinsights-shims" "3.0.1" + "@microsoft/dynamicproto-js" "^2.0.2" + "@nevware21/ts-async" ">= 0.2.4 < 2.x" + "@nevware21/ts-utils" ">= 0.9.5 < 2.x" "@microsoft/applicationinsights-web-snippet@^1.0.1": version "1.0.1" @@ -126,54 +185,104 @@ resolved "https://registry.yarnpkg.com/@microsoft/dynamicproto-js/-/dynamicproto-js-1.1.7.tgz#ede48dd3f85af14ee369c805e5ed5b84222b9fe2" integrity sha512-SK3D3aVt+5vOOccKPnGaJWB5gQ8FuKfjboUJHedMP7gu54HqSCXX5iFXhktGD8nfJb0Go30eDvs/UDoTnR2kOA== -"@opentelemetry/api@^1.0.4": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.2.0.tgz#89ef99401cde6208cff98760b67663726ef26686" - integrity sha512-0nBr+VZNKm9tvNDZFstI3Pq1fCTEDK5OZTnVKNvBNAKgd0yIvmwsP4m61rEv7ZP+tOUjWJhROpxK5MsnlF911g== +"@microsoft/dynamicproto-js@^1.1.9": + version "1.1.9" + resolved "https://registry.yarnpkg.com/@microsoft/dynamicproto-js/-/dynamicproto-js-1.1.9.tgz#7437db7aa061162ee94e4131b69a62b8dad5dea6" + integrity sha512-n1VPsljTSkthsAFYdiWfC+DKzK2WwcRp83Y1YAqdX552BstvsDjft9YXppjUzp11BPsapDoO1LDgrDB0XVsfNQ== -"@opentelemetry/core@1.7.0", "@opentelemetry/core@^1.0.1": - version "1.7.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-1.7.0.tgz#83bdd1b7a4ceafcdffd6590420657caec5f7b34c" - integrity sha512-AVqAi5uc8DrKJBimCTFUT4iFI+5eXpo4sYmGbQ0CypG0piOTHE2g9c5aSoTGYXu3CzOmJZf7pT6Xh+nwm5d6yQ== +"@microsoft/dynamicproto-js@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@microsoft/dynamicproto-js/-/dynamicproto-js-2.0.2.tgz#e57fbec2e7067d48b7e8e1e1c1d354028ef718a6" + integrity sha512-MB8trWaFREpmb037k/d0bB7T2BP7Ai24w1e1tbz3ASLB0/lwphsq3Nq8S9I5AsI5vs4zAQT+SB5nC5/dLYTiOg== dependencies: - "@opentelemetry/semantic-conventions" "1.7.0" + "@nevware21/ts-utils" ">= 0.9.4 < 2.x" -"@opentelemetry/resources@1.7.0": - version "1.7.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/resources/-/resources-1.7.0.tgz#90ccd3a6a86b4dfba4e833e73944bd64958d78c5" - integrity sha512-u1M0yZotkjyKx8dj+46Sg5thwtOTBmtRieNXqdCRiWUp6SfFiIP0bI+1XK3LhuXqXkBXA1awJZaTqKduNMStRg== +"@nevware21/ts-async@>= 0.2.4 < 2.x": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@nevware21/ts-async/-/ts-async-0.3.0.tgz#a8b97ba01065fc930de9a3f4dd4a05e862becc6c" + integrity sha512-ZUcgUH12LN/F6nzN0cYd0F/rJaMLmXr0EHVTyYfaYmK55bdwE4338uue4UiVoRqHVqNW4KDUrJc49iGogHKeWA== dependencies: - "@opentelemetry/core" "1.7.0" - "@opentelemetry/semantic-conventions" "1.7.0" + "@nevware21/ts-utils" ">= 0.10.0 < 2.x" -"@opentelemetry/sdk-trace-base@^1.0.1": - version "1.7.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.7.0.tgz#b498424e0c6340a9d80de63fd408c5c2130a60a5" - integrity sha512-Iz84C+FVOskmauh9FNnj4+VrA+hG5o+tkMzXuoesvSfunVSioXib0syVFeNXwOm4+M5GdWCuW632LVjqEXStIg== +"@nevware21/ts-utils@>= 0.10.0 < 2.x", "@nevware21/ts-utils@>= 0.9.4 < 2.x", "@nevware21/ts-utils@>= 0.9.5 < 2.x": + version "0.10.1" + resolved "https://registry.yarnpkg.com/@nevware21/ts-utils/-/ts-utils-0.10.1.tgz#aa65abc71eba06749a396598f22263d26f796ac7" + integrity sha512-pMny25NnF2/MJwdqC3Iyjm2pGIXNxni4AROpcqDeWa+td9JMUY4bUS9uU9XW+BoBRqTLUL+WURF9SOd/6OQzRg== + +"@opentelemetry/api@^1.4.1": + version "1.4.1" + resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.4.1.tgz#ff22eb2e5d476fbc2450a196e40dd243cc20c28f" + integrity sha512-O2yRJce1GOc6PAy3QxFM4NzFiWzvScDC1/5ihYBL6BUEVdq0XMWN01sppE+H6bBXbaFYipjwFLEWLg5PaSOThA== + +"@opentelemetry/core@1.15.2", "@opentelemetry/core@^1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-1.15.2.tgz#5b170bf223a2333884bbc2d29d95812cdbda7c9f" + integrity sha512-+gBv15ta96WqkHZaPpcDHiaz0utiiHZVfm2YOYSqFGrUaJpPkMoSuLBB58YFQGi6Rsb9EHos84X6X5+9JspmLw== dependencies: - "@opentelemetry/core" "1.7.0" - "@opentelemetry/resources" "1.7.0" - "@opentelemetry/semantic-conventions" "1.7.0" + "@opentelemetry/semantic-conventions" "1.15.2" -"@opentelemetry/semantic-conventions@1.7.0", "@opentelemetry/semantic-conventions@^1.0.1": - version "1.7.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.7.0.tgz#af80a1ef7cf110ea3a68242acd95648991bcd763" - integrity sha512-FGBx/Qd09lMaqQcogCHyYrFEpTx4cAjeS+48lMIR12z7LdH+zofGDVQSubN59nL6IpubfKqTeIDu9rNO28iHVA== +"@opentelemetry/instrumentation@^0.41.2": + version "0.41.2" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation/-/instrumentation-0.41.2.tgz#cae11fa64485dcf03dae331f35b315b64bc6189f" + integrity sha512-rxU72E0pKNH6ae2w5+xgVYZLzc5mlxAbGzF4shxMVK8YC2QQsfN38B2GPbj0jvrKWWNUElfclQ+YTykkNg/grw== + dependencies: + "@types/shimmer" "^1.0.2" + import-in-the-middle "1.4.2" + require-in-the-middle "^7.1.1" + semver "^7.5.1" + shimmer "^1.2.1" + +"@opentelemetry/resources@1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@opentelemetry/resources/-/resources-1.15.2.tgz#0c9e26cb65652a1402834a3c030cce6028d6dd9d" + integrity sha512-xmMRLenT9CXmm5HMbzpZ1hWhaUowQf8UB4jMjFlAxx1QzQcsD3KFNAVX/CAWzFPtllTyTplrA4JrQ7sCH3qmYw== + dependencies: + "@opentelemetry/core" "1.15.2" + "@opentelemetry/semantic-conventions" "1.15.2" + +"@opentelemetry/sdk-trace-base@^1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.15.2.tgz#4821f94033c55a6c8bbd35ae387b715b6108517a" + integrity sha512-BEaxGZbWtvnSPchV98qqqqa96AOcb41pjgvhfzDij10tkBhIu9m0Jd6tZ1tJB5ZHfHbTffqYVYE0AOGobec/EQ== + dependencies: + "@opentelemetry/core" "1.15.2" + "@opentelemetry/resources" "1.15.2" + "@opentelemetry/semantic-conventions" "1.15.2" + +"@opentelemetry/semantic-conventions@1.15.2", "@opentelemetry/semantic-conventions@^1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.15.2.tgz#3bafb5de3e20e841dff6cb3c66f4d6e9694c4241" + integrity sha512-CjbOKwk2s+3xPIMcd5UNYQzsf+v94RczbdNix9/kQh38WiQkM90sUOi3if8eyHFgiBjBjhwXrA7W3ydiSQP9mw== "@tootallnate/once@2": version "2.0.0" resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf" integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A== -"@vscode/extension-telemetry@0.7.5": - version "0.7.5" - resolved "https://registry.yarnpkg.com/@vscode/extension-telemetry/-/extension-telemetry-0.7.5.tgz#bf965731816e08c3f146f96d901ec67954fc913b" - integrity sha512-fJ5y3TcpqqkFYHneabYaoB4XAhDdVflVm+TDKshw9VOs77jkgNS4UA7LNXrWeO0eDne3Sh3JgURf+xzc1rk69w== +"@types/shimmer@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@types/shimmer/-/shimmer-1.0.2.tgz#93eb2c243c351f3f17d5c580c7467ae5d686b65f" + integrity sha512-dKkr1bTxbEsFlh2ARpKzcaAmsYixqt9UyCdoEZk8rHyE4iQYcDCyvSjDSf7JUWJHlJiTtbIoQjxKh6ViywqDAg== + +"@vscode/extension-telemetry@^0.8.4": + version "0.8.4" + resolved "https://registry.yarnpkg.com/@vscode/extension-telemetry/-/extension-telemetry-0.8.4.tgz#c078c6f55df1c9e0592de3b4ce0f685dd345bfe7" + integrity sha512-UqM9+KZDDK3MyoHTsg6XNM+XO6pweQxzCpqJz33BoBEYAGsbBviRYcVpJglgay2oReuDD2pOI1Nio3BKNDLhWA== dependencies: - "@microsoft/1ds-core-js" "^3.2.8" - "@microsoft/1ds-post-js" "^3.2.8" - "@microsoft/applicationinsights-web-basic" "^2.8.9" - applicationinsights "2.4.1" + "@microsoft/1ds-core-js" "^3.2.13" + "@microsoft/1ds-post-js" "^3.2.13" + "@microsoft/applicationinsights-web-basic" "^3.0.2" + applicationinsights "^2.7.1" + +acorn-import-assertions@^1.9.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz#507276249d684797c84e0734ef84860334cfb1ac" + integrity sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA== + +acorn@^8.8.2: + version "8.10.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5" + integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw== agent-base@6: version "6.0.2" @@ -182,22 +291,24 @@ agent-base@6: dependencies: debug "4" -applicationinsights@2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/applicationinsights/-/applicationinsights-2.4.1.tgz#4de4c4dd3c7c4a44445cfbf3d15808fc0dcc423d" - integrity sha512-0n0Ikd0gzSm460xm+M0UTWIwXrhrH/0bqfZatcJjYObWyefxfAxapGEyNnSGd1Tg90neHz+Yhf+Ff/zgvPiQYA== +applicationinsights@^2.7.1: + version "2.7.3" + resolved "https://registry.yarnpkg.com/applicationinsights/-/applicationinsights-2.7.3.tgz#8781454d29c0b14c9773f2e892b4cf5e7468ffa5" + integrity sha512-JY8+kTEkjbA+kAVNWDtpfW2lqsrDALfDXuxOs74KLPu2y13fy/9WB52V4LfYVTVcW1/jYOXjTxNS2gPZIDh1iw== dependencies: - "@azure/core-auth" "^1.4.0" - "@azure/core-rest-pipeline" "^1.10.0" + "@azure/core-auth" "^1.5.0" + "@azure/core-rest-pipeline" "1.10.1" + "@azure/core-util" "1.2.0" + "@azure/opentelemetry-instrumentation-azure-sdk" "^1.0.0-beta.5" "@microsoft/applicationinsights-web-snippet" "^1.0.1" - "@opentelemetry/api" "^1.0.4" - "@opentelemetry/core" "^1.0.1" - "@opentelemetry/sdk-trace-base" "^1.0.1" - "@opentelemetry/semantic-conventions" "^1.0.1" + "@opentelemetry/api" "^1.4.1" + "@opentelemetry/core" "^1.15.2" + "@opentelemetry/sdk-trace-base" "^1.15.2" + "@opentelemetry/semantic-conventions" "^1.15.2" cls-hooked "^4.2.2" continuation-local-storage "^3.2.1" - diagnostic-channel "1.1.0" - diagnostic-channel-publishers "1.0.5" + diagnostic-channel "1.1.1" + diagnostic-channel-publishers "1.0.7" async-hook-jl@^1.7.6: version "1.7.6" @@ -219,6 +330,11 @@ asynckit@^0.4.0: resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== +cjs-module-lexer@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz#6c370ab19f8a3394e318fe682686ec0ac684d107" + integrity sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ== + cls-hooked@^4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/cls-hooked/-/cls-hooked-4.2.2.tgz#ad2e9a4092680cdaffeb2d3551da0e225eae1908" @@ -243,7 +359,7 @@ continuation-local-storage@^3.2.1: async-listener "^0.6.0" emitter-listener "^1.1.1" -debug@4: +debug@4, debug@^4.1.1: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== @@ -255,17 +371,17 @@ delayed-stream@~1.0.0: resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== -diagnostic-channel-publishers@1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/diagnostic-channel-publishers/-/diagnostic-channel-publishers-1.0.5.tgz#df8c317086c50f5727fdfb5d2fce214d2e4130ae" - integrity sha512-dJwUS0915pkjjimPJVDnS/QQHsH0aOYhnZsLJdnZIMOrB+csj8RnZhWTuwnm8R5v3Z7OZs+ksv5luC14DGB7eg== +diagnostic-channel-publishers@1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/diagnostic-channel-publishers/-/diagnostic-channel-publishers-1.0.7.tgz#9b7f8d5ee1295481aee19c827d917e96fedf2c4a" + integrity sha512-SEECbY5AiVt6DfLkhkaHNeshg1CogdLLANA8xlG/TKvS+XUgvIKl7VspJGYiEdL5OUyzMVnr7o0AwB7f+/Mjtg== -diagnostic-channel@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/diagnostic-channel/-/diagnostic-channel-1.1.0.tgz#6985e9dfedfbc072d91dc4388477e4087147756e" - integrity sha512-fwujyMe1gj6rk6dYi9hMZm0c8Mz8NDMVl2LB4iaYh3+LIAThZC8RKFGXWG0IML2OxAit/ZFRgZhMkhQ3d/bobQ== +diagnostic-channel@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/diagnostic-channel/-/diagnostic-channel-1.1.1.tgz#44b60972de9ee055c16216535b0e9db3f6a0efd0" + integrity sha512-r2HV5qFkUICyoaKlBEpLKHjxMXATUf/l+h8UZPGBHGLy4DDiY2sOLcIctax4eRnTw5wH2jTMExLntGPJ8eOJxw== dependencies: - semver "^5.3.0" + semver "^7.5.3" emitter-listener@^1.0.1, emitter-listener@^1.1.1: version "1.1.2" @@ -283,6 +399,18 @@ form-data@^4.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + http-proxy-agent@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz#5129800203520d434f142bc78ff3c170800f2b43" @@ -300,6 +428,30 @@ https-proxy-agent@^5.0.0: agent-base "6" debug "4" +import-in-the-middle@1.4.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/import-in-the-middle/-/import-in-the-middle-1.4.2.tgz#2a266676e3495e72c04bbaa5ec14756ba168391b" + integrity sha512-9WOz1Yh/cvO/p69sxRmhyQwrIGGSp7EIdcb+fFNVi7CzQGQB8U1/1XrKVSbEd/GNOAeM0peJtmi7+qphe7NvAw== + dependencies: + acorn "^8.8.2" + acorn-import-assertions "^1.9.0" + cjs-module-lexer "^1.2.2" + module-details-from-path "^1.0.3" + +is-core-module@^2.13.0: + version "2.13.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.0.tgz#bb52aa6e2cbd49a30c2ba68c42bf3435ba6072db" + integrity sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ== + dependencies: + has "^1.0.3" + +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + mime-db@1.52.0: version "1.52.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" @@ -312,17 +464,52 @@ mime-types@^2.1.12: dependencies: mime-db "1.52.0" +module-details-from-path@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/module-details-from-path/-/module-details-from-path-1.0.3.tgz#114c949673e2a8a35e9d35788527aa37b679da2b" + integrity sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A== + ms@2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +require-in-the-middle@^7.1.1: + version "7.2.0" + resolved "https://registry.yarnpkg.com/require-in-the-middle/-/require-in-the-middle-7.2.0.tgz#b539de8f00955444dc8aed95e17c69b0a4f10fcf" + integrity sha512-3TLx5TGyAY6AOqLBoXmHkNql0HIf2RGbuMgCDT2WO/uGVAPJs6h7Kl+bN6TIZGd9bWhWPwnDnTHGtW8Iu77sdw== + dependencies: + debug "^4.1.1" + module-details-from-path "^1.0.3" + resolve "^1.22.1" + +resolve@^1.22.1: + version "1.22.4" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.4.tgz#1dc40df46554cdaf8948a486a10f6ba1e2026c34" + integrity sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg== + dependencies: + is-core-module "^2.13.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + semver@^5.3.0, semver@^5.4.1: version "5.7.2" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== -shimmer@^1.1.0, shimmer@^1.2.0: +semver@^7.5.1, semver@^7.5.3: + version "7.5.4" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" + integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== + dependencies: + lru-cache "^6.0.0" + +shimmer@^1.1.0, shimmer@^1.2.0, shimmer@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/shimmer/-/shimmer-1.2.1.tgz#610859f7de327b587efebf501fb43117f9aff337" integrity sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw== @@ -332,6 +519,11 @@ stack-chain@^1.3.7: resolved "https://registry.yarnpkg.com/stack-chain/-/stack-chain-1.3.7.tgz#d192c9ff4ea6a22c94c4dd459171e3f00cea1285" integrity sha512-D8cWtWVdIe/jBA7v5p5Hwl5yOSOrmZPWDPe2KxQ5UAGD+nxbxU0lKXA4h85Ta6+qgdKVL3vUxsbIZjc1kBG7ug== +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + tslib@^2.2.0: version "2.4.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.1.tgz#0d0bfbaac2880b91e22df0768e55be9753a5b17e" @@ -346,3 +538,8 @@ vscode-uri@^3.0.6: version "3.0.6" resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-3.0.6.tgz#5e6e2e1a4170543af30151b561a41f71db1d6f91" integrity sha512-fmL7V1eiDBFRRnu+gfRWTzyPpNIHJTc4mWnFkwBUmO9U3KPgJAmTx7oxi2bl/Rh6HLdU7+4C9wlj0k2E4AdKFQ== + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== diff --git a/extensions/merge-conflict/package.json b/extensions/merge-conflict/package.json index 00a7136cff2..751e85c3da2 100644 --- a/extensions/merge-conflict/package.json +++ b/extensions/merge-conflict/package.json @@ -166,7 +166,7 @@ } }, "dependencies": { - "@vscode/extension-telemetry": "0.7.5" + "@vscode/extension-telemetry": "^0.8.4" }, "devDependencies": { "@types/node": "18.x" diff --git a/extensions/merge-conflict/yarn.lock b/extensions/merge-conflict/yarn.lock index f07c9a13701..d214c5e4447 100644 --- a/extensions/merge-conflict/yarn.lock +++ b/extensions/merge-conflict/yarn.lock @@ -17,7 +17,16 @@ "@azure/abort-controller" "^1.0.0" tslib "^2.2.0" -"@azure/core-rest-pipeline@^1.10.0": +"@azure/core-auth@^1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@azure/core-auth/-/core-auth-1.5.0.tgz#a41848c5c31cb3b7c84c409885267d55a2c92e44" + integrity sha512-udzoBuYG1VBoHVohDTrvKjyzel34zt77Bhp7dQntVGGD0ehVq48owENbBG8fIgkHRNUBQH5k1r0hpoMu5L8+kw== + dependencies: + "@azure/abort-controller" "^1.0.0" + "@azure/core-util" "^1.1.0" + tslib "^2.2.0" + +"@azure/core-rest-pipeline@1.10.1": version "1.10.1" resolved "https://registry.yarnpkg.com/@azure/core-rest-pipeline/-/core-rest-pipeline-1.10.1.tgz#348290847ca31b9eecf9cf5de7519aaccdd30968" integrity sha512-Kji9k6TOFRDB5ZMTw8qUf2IJ+CeJtsuMdAHox9eqpTf1cefiNMpzrfnF6sINEBZJsaVaWgQ0o48B6kcUH68niA== @@ -33,13 +42,21 @@ tslib "^2.2.0" uuid "^8.3.0" -"@azure/core-tracing@^1.0.1": +"@azure/core-tracing@^1.0.0", "@azure/core-tracing@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@azure/core-tracing/-/core-tracing-1.0.1.tgz#352a38cbea438c4a83c86b314f48017d70ba9503" integrity sha512-I5CGMoLtX+pI17ZdiFJZgxMJApsK6jjfm85hpgp3oazCdq5Wxgh4wMr7ge/TTWW1B5WBuvIOI1fMU/FrOAMKrw== dependencies: tslib "^2.2.0" +"@azure/core-util@1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@azure/core-util/-/core-util-1.2.0.tgz#3499deba1fc36dda6f1912b791809b6f15d4a392" + integrity sha512-ffGIw+Qs8bNKNLxz5UPkz4/VBM/EZY07mPve1ZYFqYUdPwFqRj0RPk0U7LZMOfT7GCck9YjuT1Rfp1PApNl1ng== + dependencies: + "@azure/abort-controller" "^1.0.0" + tslib "^2.2.0" + "@azure/core-util@^1.0.0": version "1.1.1" resolved "https://registry.yarnpkg.com/@azure/core-util/-/core-util-1.1.1.tgz#8f87b3dd468795df0f0849d9f096c3e7b29452c1" @@ -48,6 +65,14 @@ "@azure/abort-controller" "^1.0.0" tslib "^2.2.0" +"@azure/core-util@^1.1.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@azure/core-util/-/core-util-1.4.0.tgz#c120a56b3e48a9e4d20619a0b00268ae9de891c7" + integrity sha512-eGAyJpm3skVQoLiRqm/xPa+SXi/NPDdSHMxbRAz2lSprd+Zs+qrpQGQQ2VQ3Nttu+nSZR4XoYQC71LbEI7jsig== + dependencies: + "@azure/abort-controller" "^1.0.0" + tslib "^2.2.0" + "@azure/logger@^1.0.0": version "1.0.3" resolved "https://registry.yarnpkg.com/@azure/logger/-/logger-1.0.3.tgz#6e36704aa51be7d4a1bae24731ea580836293c96" @@ -55,66 +80,100 @@ dependencies: tslib "^2.2.0" -"@microsoft/1ds-core-js@3.2.8", "@microsoft/1ds-core-js@^3.2.8": - version "3.2.8" - resolved "https://registry.yarnpkg.com/@microsoft/1ds-core-js/-/1ds-core-js-3.2.8.tgz#1b6b7d9bb858238c818ccf4e4b58ece7aeae5760" - integrity sha512-9o9SUAamJiTXIYwpkQDuueYt83uZfXp8zp8YFix1IwVPwC9RmE36T2CX9gXOeq1nDckOuOduYpA8qHvdh5BGfQ== +"@azure/opentelemetry-instrumentation-azure-sdk@^1.0.0-beta.5": + version "1.0.0-beta.5" + resolved "https://registry.yarnpkg.com/@azure/opentelemetry-instrumentation-azure-sdk/-/opentelemetry-instrumentation-azure-sdk-1.0.0-beta.5.tgz#78809e6c005d08450701e5d37f087f6fce2f86eb" + integrity sha512-fsUarKQDvjhmBO4nIfaZkfNSApm1hZBzcvpNbSrXdcUBxu7lRvKsV5DnwszX7cnhLyVOW9yl1uigtRQ1yDANjA== dependencies: - "@microsoft/applicationinsights-core-js" "2.8.9" + "@azure/core-tracing" "^1.0.0" + "@azure/logger" "^1.0.0" + "@opentelemetry/api" "^1.4.1" + "@opentelemetry/core" "^1.15.2" + "@opentelemetry/instrumentation" "^0.41.2" + tslib "^2.2.0" + +"@microsoft/1ds-core-js@3.2.13", "@microsoft/1ds-core-js@^3.2.13": + version "3.2.13" + resolved "https://registry.yarnpkg.com/@microsoft/1ds-core-js/-/1ds-core-js-3.2.13.tgz#0c105ed75091bae3f1555c0334704fa9911c58fb" + integrity sha512-CluYTRWcEk0ObG5EWFNWhs87e2qchJUn0p2D21ZUa3PWojPZfPSBs4//WIE0MYV8Qg1Hdif2ZTwlM7TbYUjfAg== + dependencies: + "@microsoft/applicationinsights-core-js" "2.8.15" "@microsoft/applicationinsights-shims" "^2.0.2" "@microsoft/dynamicproto-js" "^1.1.7" -"@microsoft/1ds-post-js@^3.2.8": - version "3.2.8" - resolved "https://registry.yarnpkg.com/@microsoft/1ds-post-js/-/1ds-post-js-3.2.8.tgz#46793842cca161bf7a2a5b6053c349f429e55110" - integrity sha512-SjlRoNcXcXBH6WQD/5SkkaCHIVqldH3gDu+bI7YagrOVJ5APxwT1Duw9gm3L1FjFa9S2i81fvJ3EVSKpp9wULA== +"@microsoft/1ds-post-js@^3.2.13": + version "3.2.13" + resolved "https://registry.yarnpkg.com/@microsoft/1ds-post-js/-/1ds-post-js-3.2.13.tgz#560aacac8a92fdbb79e8c2ebcb293d56e19f51aa" + integrity sha512-HgS574fdD19Bo2vPguyznL4eDw7Pcm1cVNpvbvBLWiW3x4e1FCQ3VMXChWnAxCae8Hb0XqlA2sz332ZobBavTA== dependencies: - "@microsoft/1ds-core-js" "3.2.8" + "@microsoft/1ds-core-js" "3.2.13" "@microsoft/applicationinsights-shims" "^2.0.2" "@microsoft/dynamicproto-js" "^1.1.7" -"@microsoft/applicationinsights-channel-js@2.8.9": - version "2.8.9" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-channel-js/-/applicationinsights-channel-js-2.8.9.tgz#840656f3c716de8b3eb0a98c122aa1b92bb8ebfb" - integrity sha512-fMBsAEB7pWtPn43y72q9Xy5E5y55r6gMuDQqRRccccVoQDPXyS57VCj5IdATblctru0C6A8XpL2vRyNmEsu0Vg== +"@microsoft/applicationinsights-channel-js@3.0.2": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-channel-js/-/applicationinsights-channel-js-3.0.2.tgz#be49fbf74831c7b8c97950027c5052ea99d2a8a5" + integrity sha512-jDBNKbCHsJgmpv0CKNhJ/uN9ZphvfGdb93Svk+R4LjO8L3apNNMbDDPxBvXXi0uigRmA1TBcmyBG4IRKjabGhw== dependencies: - "@microsoft/applicationinsights-common" "2.8.9" - "@microsoft/applicationinsights-core-js" "2.8.9" - "@microsoft/applicationinsights-shims" "2.0.2" - "@microsoft/dynamicproto-js" "^1.1.7" + "@microsoft/applicationinsights-common" "3.0.2" + "@microsoft/applicationinsights-core-js" "3.0.2" + "@microsoft/applicationinsights-shims" "3.0.1" + "@microsoft/dynamicproto-js" "^2.0.2" + "@nevware21/ts-async" ">= 0.2.4 < 2.x" + "@nevware21/ts-utils" ">= 0.9.5 < 2.x" -"@microsoft/applicationinsights-common@2.8.9": - version "2.8.9" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-common/-/applicationinsights-common-2.8.9.tgz#a75e4a3143a7fd797687830c0ddd2069fd900827" - integrity sha512-mObn1moElyxZaGIRF/IU3cOaeKMgxghXnYEoHNUCA2e+rNwBIgxjyKkblFIpmGuHf4X7Oz3o3yBWpaC6AoMpig== +"@microsoft/applicationinsights-common@3.0.2": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-common/-/applicationinsights-common-3.0.2.tgz#37670bb07f4858ed41ff9759119e0759007d6e05" + integrity sha512-y+WXWop+OVim954Cu1uyYMnNx6PWO8okHpZIQi/1YSqtqaYdtJVPv4P0AVzwJdohxzVfgzKvqj9nec/VWqE2Zg== dependencies: - "@microsoft/applicationinsights-core-js" "2.8.9" - "@microsoft/applicationinsights-shims" "2.0.2" - "@microsoft/dynamicproto-js" "^1.1.7" + "@microsoft/applicationinsights-core-js" "3.0.2" + "@microsoft/applicationinsights-shims" "3.0.1" + "@microsoft/dynamicproto-js" "^2.0.2" + "@nevware21/ts-utils" ">= 0.9.5 < 2.x" -"@microsoft/applicationinsights-core-js@2.8.9": - version "2.8.9" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-2.8.9.tgz#0e5d207acfae6986a6fc97249eeb6117e523bf1b" - integrity sha512-HRuIuZ6aOWezcg/G5VyFDDWGL8hDNe/ljPP01J7ImH2kRPEgbtcfPSUMjkamGMefgdq81GZsSoC/NNGTP4pp2w== +"@microsoft/applicationinsights-core-js@2.8.15": + version "2.8.15" + resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-2.8.15.tgz#8fa466474260e01967fe649f14dd9e5ff91dcdc8" + integrity sha512-yYAs9MyjGr2YijQdUSN9mVgT1ijI1FPMgcffpaPmYbHAVbQmF7bXudrBWHxmLzJlwl5rfep+Zgjli2e67lwUqQ== dependencies: "@microsoft/applicationinsights-shims" "2.0.2" - "@microsoft/dynamicproto-js" "^1.1.7" + "@microsoft/dynamicproto-js" "^1.1.9" + +"@microsoft/applicationinsights-core-js@3.0.2": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-3.0.2.tgz#108e20df8c162bec92b1f66f9de2530a25d9f51a" + integrity sha512-WQhVhzlRlLDrQzn3OShCW/pL3BW5WC57t0oywSknX3q7lMzI3jDg7Ihh0iuIcNTzGCTbDkuqr4d6IjEDWIMtJQ== + dependencies: + "@microsoft/applicationinsights-shims" "3.0.1" + "@microsoft/dynamicproto-js" "^2.0.2" + "@nevware21/ts-async" ">= 0.2.4 < 2.x" + "@nevware21/ts-utils" ">= 0.9.5 < 2.x" "@microsoft/applicationinsights-shims@2.0.2", "@microsoft/applicationinsights-shims@^2.0.2": version "2.0.2" resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-shims/-/applicationinsights-shims-2.0.2.tgz#92b36a09375e2d9cb2b4203383b05772be837085" integrity sha512-PoHEgsnmcqruLNHZ/amACqdJ6YYQpED0KSRe6J7gIJTtpZC1FfFU9b1fmDKDKtFoUSrPzEh1qzO3kmRZP0betg== -"@microsoft/applicationinsights-web-basic@^2.8.9": - version "2.8.9" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-web-basic/-/applicationinsights-web-basic-2.8.9.tgz#eed2f3d1e19069962ed2155915c1656e6936e1d5" - integrity sha512-CH0J8JFOy7MjK8JO4pXXU+EML+Ilix+94PMZTX5EJlBU1in+mrik74/8qSg3UC4ekPi12KwrXaHCQSVC3WseXQ== +"@microsoft/applicationinsights-shims@3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-shims/-/applicationinsights-shims-3.0.1.tgz#3865b73ace8405b9c4618cc5c571f2fe3876f06f" + integrity sha512-DKwboF47H1nb33rSUfjqI6ryX29v+2QWcTrRvcQDA32AZr5Ilkr7whOOSsD1aBzwqX0RJEIP1Z81jfE3NBm/Lg== dependencies: - "@microsoft/applicationinsights-channel-js" "2.8.9" - "@microsoft/applicationinsights-common" "2.8.9" - "@microsoft/applicationinsights-core-js" "2.8.9" - "@microsoft/applicationinsights-shims" "2.0.2" - "@microsoft/dynamicproto-js" "^1.1.7" + "@nevware21/ts-utils" ">= 0.9.4 < 2.x" + +"@microsoft/applicationinsights-web-basic@^3.0.2": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-web-basic/-/applicationinsights-web-basic-3.0.2.tgz#f777a4d24b79dde3ae396d3b819e1fce06b7240a" + integrity sha512-6Lq0DE/pZp9RvSV+weGbcxN1NDmfczj6gNPhvZKV2YSQ3RK0LZE3+wjTWLXfuStq8a+nCBdsRpWk8tOKgsoxcg== + dependencies: + "@microsoft/applicationinsights-channel-js" "3.0.2" + "@microsoft/applicationinsights-common" "3.0.2" + "@microsoft/applicationinsights-core-js" "3.0.2" + "@microsoft/applicationinsights-shims" "3.0.1" + "@microsoft/dynamicproto-js" "^2.0.2" + "@nevware21/ts-async" ">= 0.2.4 < 2.x" + "@nevware21/ts-utils" ">= 0.9.5 < 2.x" "@microsoft/applicationinsights-web-snippet@^1.0.1": version "1.0.1" @@ -126,39 +185,74 @@ resolved "https://registry.yarnpkg.com/@microsoft/dynamicproto-js/-/dynamicproto-js-1.1.7.tgz#ede48dd3f85af14ee369c805e5ed5b84222b9fe2" integrity sha512-SK3D3aVt+5vOOccKPnGaJWB5gQ8FuKfjboUJHedMP7gu54HqSCXX5iFXhktGD8nfJb0Go30eDvs/UDoTnR2kOA== -"@opentelemetry/api@^1.0.4": - version "1.3.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.3.0.tgz#27c6f776ac3c1c616651e506a89f438a0ed6a055" - integrity sha512-YveTnGNsFFixTKJz09Oi4zYkiLT5af3WpZDu4aIUM7xX+2bHAkOJayFTVQd6zB8kkWPpbua4Ha6Ql00grdLlJQ== +"@microsoft/dynamicproto-js@^1.1.9": + version "1.1.9" + resolved "https://registry.yarnpkg.com/@microsoft/dynamicproto-js/-/dynamicproto-js-1.1.9.tgz#7437db7aa061162ee94e4131b69a62b8dad5dea6" + integrity sha512-n1VPsljTSkthsAFYdiWfC+DKzK2WwcRp83Y1YAqdX552BstvsDjft9YXppjUzp11BPsapDoO1LDgrDB0XVsfNQ== -"@opentelemetry/core@1.8.0", "@opentelemetry/core@^1.0.1": - version "1.8.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-1.8.0.tgz#cca18594dd48ded6dc0d08c7e789c79af0315934" - integrity sha512-6SDjwBML4Am0AQmy7z1j6HGrWDgeK8awBRUvl1PGw6HayViMk4QpnUXvv4HTHisecgVBy43NE/cstWprm8tIfw== +"@microsoft/dynamicproto-js@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@microsoft/dynamicproto-js/-/dynamicproto-js-2.0.2.tgz#e57fbec2e7067d48b7e8e1e1c1d354028ef718a6" + integrity sha512-MB8trWaFREpmb037k/d0bB7T2BP7Ai24w1e1tbz3ASLB0/lwphsq3Nq8S9I5AsI5vs4zAQT+SB5nC5/dLYTiOg== dependencies: - "@opentelemetry/semantic-conventions" "1.8.0" + "@nevware21/ts-utils" ">= 0.9.4 < 2.x" -"@opentelemetry/resources@1.8.0": - version "1.8.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/resources/-/resources-1.8.0.tgz#260be9742cf7bceccc0db928d8ca8d64391acfe3" - integrity sha512-KSyMH6Jvss/PFDy16z5qkCK0ERlpyqixb1xwb73wLMvVq+j7i89lobDjw3JkpCcd1Ws0J6jAI4fw28Zufj2ssg== +"@nevware21/ts-async@>= 0.2.4 < 2.x": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@nevware21/ts-async/-/ts-async-0.3.0.tgz#a8b97ba01065fc930de9a3f4dd4a05e862becc6c" + integrity sha512-ZUcgUH12LN/F6nzN0cYd0F/rJaMLmXr0EHVTyYfaYmK55bdwE4338uue4UiVoRqHVqNW4KDUrJc49iGogHKeWA== dependencies: - "@opentelemetry/core" "1.8.0" - "@opentelemetry/semantic-conventions" "1.8.0" + "@nevware21/ts-utils" ">= 0.10.0 < 2.x" -"@opentelemetry/sdk-trace-base@^1.0.1": - version "1.8.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.8.0.tgz#70713aab90978a16dea188c8335209f857be7384" - integrity sha512-iH41m0UTddnCKJzZx3M85vlhKzRcmT48pUeBbnzsGrq4nIay1oWVHKM5nhB5r8qRDGvd/n7f/YLCXClxwM0tvA== +"@nevware21/ts-utils@>= 0.10.0 < 2.x", "@nevware21/ts-utils@>= 0.9.4 < 2.x", "@nevware21/ts-utils@>= 0.9.5 < 2.x": + version "0.10.1" + resolved "https://registry.yarnpkg.com/@nevware21/ts-utils/-/ts-utils-0.10.1.tgz#aa65abc71eba06749a396598f22263d26f796ac7" + integrity sha512-pMny25NnF2/MJwdqC3Iyjm2pGIXNxni4AROpcqDeWa+td9JMUY4bUS9uU9XW+BoBRqTLUL+WURF9SOd/6OQzRg== + +"@opentelemetry/api@^1.4.1": + version "1.4.1" + resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.4.1.tgz#ff22eb2e5d476fbc2450a196e40dd243cc20c28f" + integrity sha512-O2yRJce1GOc6PAy3QxFM4NzFiWzvScDC1/5ihYBL6BUEVdq0XMWN01sppE+H6bBXbaFYipjwFLEWLg5PaSOThA== + +"@opentelemetry/core@1.15.2", "@opentelemetry/core@^1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-1.15.2.tgz#5b170bf223a2333884bbc2d29d95812cdbda7c9f" + integrity sha512-+gBv15ta96WqkHZaPpcDHiaz0utiiHZVfm2YOYSqFGrUaJpPkMoSuLBB58YFQGi6Rsb9EHos84X6X5+9JspmLw== dependencies: - "@opentelemetry/core" "1.8.0" - "@opentelemetry/resources" "1.8.0" - "@opentelemetry/semantic-conventions" "1.8.0" + "@opentelemetry/semantic-conventions" "1.15.2" -"@opentelemetry/semantic-conventions@1.8.0", "@opentelemetry/semantic-conventions@^1.0.1": - version "1.8.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.8.0.tgz#fe2aa90e6df050a11cd57f5c0f47b0641fd2cad3" - integrity sha512-TYh1MRcm4JnvpqtqOwT9WYaBYY4KERHdToxs/suDTLviGRsQkIjS5yYROTYTSJQUnYLOn/TuOh5GoMwfLSU+Ew== +"@opentelemetry/instrumentation@^0.41.2": + version "0.41.2" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation/-/instrumentation-0.41.2.tgz#cae11fa64485dcf03dae331f35b315b64bc6189f" + integrity sha512-rxU72E0pKNH6ae2w5+xgVYZLzc5mlxAbGzF4shxMVK8YC2QQsfN38B2GPbj0jvrKWWNUElfclQ+YTykkNg/grw== + dependencies: + "@types/shimmer" "^1.0.2" + import-in-the-middle "1.4.2" + require-in-the-middle "^7.1.1" + semver "^7.5.1" + shimmer "^1.2.1" + +"@opentelemetry/resources@1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@opentelemetry/resources/-/resources-1.15.2.tgz#0c9e26cb65652a1402834a3c030cce6028d6dd9d" + integrity sha512-xmMRLenT9CXmm5HMbzpZ1hWhaUowQf8UB4jMjFlAxx1QzQcsD3KFNAVX/CAWzFPtllTyTplrA4JrQ7sCH3qmYw== + dependencies: + "@opentelemetry/core" "1.15.2" + "@opentelemetry/semantic-conventions" "1.15.2" + +"@opentelemetry/sdk-trace-base@^1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.15.2.tgz#4821f94033c55a6c8bbd35ae387b715b6108517a" + integrity sha512-BEaxGZbWtvnSPchV98qqqqa96AOcb41pjgvhfzDij10tkBhIu9m0Jd6tZ1tJB5ZHfHbTffqYVYE0AOGobec/EQ== + dependencies: + "@opentelemetry/core" "1.15.2" + "@opentelemetry/resources" "1.15.2" + "@opentelemetry/semantic-conventions" "1.15.2" + +"@opentelemetry/semantic-conventions@1.15.2", "@opentelemetry/semantic-conventions@^1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.15.2.tgz#3bafb5de3e20e841dff6cb3c66f4d6e9694c4241" + integrity sha512-CjbOKwk2s+3xPIMcd5UNYQzsf+v94RczbdNix9/kQh38WiQkM90sUOi3if8eyHFgiBjBjhwXrA7W3ydiSQP9mw== "@tootallnate/once@2": version "2.0.0" @@ -170,15 +264,30 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-18.15.13.tgz#f64277c341150c979e42b00e4ac289290c9df469" integrity sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q== -"@vscode/extension-telemetry@0.7.5": - version "0.7.5" - resolved "https://registry.yarnpkg.com/@vscode/extension-telemetry/-/extension-telemetry-0.7.5.tgz#bf965731816e08c3f146f96d901ec67954fc913b" - integrity sha512-fJ5y3TcpqqkFYHneabYaoB4XAhDdVflVm+TDKshw9VOs77jkgNS4UA7LNXrWeO0eDne3Sh3JgURf+xzc1rk69w== +"@types/shimmer@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@types/shimmer/-/shimmer-1.0.2.tgz#93eb2c243c351f3f17d5c580c7467ae5d686b65f" + integrity sha512-dKkr1bTxbEsFlh2ARpKzcaAmsYixqt9UyCdoEZk8rHyE4iQYcDCyvSjDSf7JUWJHlJiTtbIoQjxKh6ViywqDAg== + +"@vscode/extension-telemetry@^0.8.4": + version "0.8.4" + resolved "https://registry.yarnpkg.com/@vscode/extension-telemetry/-/extension-telemetry-0.8.4.tgz#c078c6f55df1c9e0592de3b4ce0f685dd345bfe7" + integrity sha512-UqM9+KZDDK3MyoHTsg6XNM+XO6pweQxzCpqJz33BoBEYAGsbBviRYcVpJglgay2oReuDD2pOI1Nio3BKNDLhWA== dependencies: - "@microsoft/1ds-core-js" "^3.2.8" - "@microsoft/1ds-post-js" "^3.2.8" - "@microsoft/applicationinsights-web-basic" "^2.8.9" - applicationinsights "2.4.1" + "@microsoft/1ds-core-js" "^3.2.13" + "@microsoft/1ds-post-js" "^3.2.13" + "@microsoft/applicationinsights-web-basic" "^3.0.2" + applicationinsights "^2.7.1" + +acorn-import-assertions@^1.9.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz#507276249d684797c84e0734ef84860334cfb1ac" + integrity sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA== + +acorn@^8.8.2: + version "8.10.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5" + integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw== agent-base@6: version "6.0.2" @@ -187,22 +296,24 @@ agent-base@6: dependencies: debug "4" -applicationinsights@2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/applicationinsights/-/applicationinsights-2.4.1.tgz#4de4c4dd3c7c4a44445cfbf3d15808fc0dcc423d" - integrity sha512-0n0Ikd0gzSm460xm+M0UTWIwXrhrH/0bqfZatcJjYObWyefxfAxapGEyNnSGd1Tg90neHz+Yhf+Ff/zgvPiQYA== +applicationinsights@^2.7.1: + version "2.7.3" + resolved "https://registry.yarnpkg.com/applicationinsights/-/applicationinsights-2.7.3.tgz#8781454d29c0b14c9773f2e892b4cf5e7468ffa5" + integrity sha512-JY8+kTEkjbA+kAVNWDtpfW2lqsrDALfDXuxOs74KLPu2y13fy/9WB52V4LfYVTVcW1/jYOXjTxNS2gPZIDh1iw== dependencies: - "@azure/core-auth" "^1.4.0" - "@azure/core-rest-pipeline" "^1.10.0" + "@azure/core-auth" "^1.5.0" + "@azure/core-rest-pipeline" "1.10.1" + "@azure/core-util" "1.2.0" + "@azure/opentelemetry-instrumentation-azure-sdk" "^1.0.0-beta.5" "@microsoft/applicationinsights-web-snippet" "^1.0.1" - "@opentelemetry/api" "^1.0.4" - "@opentelemetry/core" "^1.0.1" - "@opentelemetry/sdk-trace-base" "^1.0.1" - "@opentelemetry/semantic-conventions" "^1.0.1" + "@opentelemetry/api" "^1.4.1" + "@opentelemetry/core" "^1.15.2" + "@opentelemetry/sdk-trace-base" "^1.15.2" + "@opentelemetry/semantic-conventions" "^1.15.2" cls-hooked "^4.2.2" continuation-local-storage "^3.2.1" - diagnostic-channel "1.1.0" - diagnostic-channel-publishers "1.0.5" + diagnostic-channel "1.1.1" + diagnostic-channel-publishers "1.0.7" async-hook-jl@^1.7.6: version "1.7.6" @@ -224,6 +335,11 @@ asynckit@^0.4.0: resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== +cjs-module-lexer@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz#6c370ab19f8a3394e318fe682686ec0ac684d107" + integrity sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ== + cls-hooked@^4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/cls-hooked/-/cls-hooked-4.2.2.tgz#ad2e9a4092680cdaffeb2d3551da0e225eae1908" @@ -248,7 +364,7 @@ continuation-local-storage@^3.2.1: async-listener "^0.6.0" emitter-listener "^1.1.1" -debug@4: +debug@4, debug@^4.1.1: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== @@ -260,17 +376,17 @@ delayed-stream@~1.0.0: resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== -diagnostic-channel-publishers@1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/diagnostic-channel-publishers/-/diagnostic-channel-publishers-1.0.5.tgz#df8c317086c50f5727fdfb5d2fce214d2e4130ae" - integrity sha512-dJwUS0915pkjjimPJVDnS/QQHsH0aOYhnZsLJdnZIMOrB+csj8RnZhWTuwnm8R5v3Z7OZs+ksv5luC14DGB7eg== +diagnostic-channel-publishers@1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/diagnostic-channel-publishers/-/diagnostic-channel-publishers-1.0.7.tgz#9b7f8d5ee1295481aee19c827d917e96fedf2c4a" + integrity sha512-SEECbY5AiVt6DfLkhkaHNeshg1CogdLLANA8xlG/TKvS+XUgvIKl7VspJGYiEdL5OUyzMVnr7o0AwB7f+/Mjtg== -diagnostic-channel@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/diagnostic-channel/-/diagnostic-channel-1.1.0.tgz#6985e9dfedfbc072d91dc4388477e4087147756e" - integrity sha512-fwujyMe1gj6rk6dYi9hMZm0c8Mz8NDMVl2LB4iaYh3+LIAThZC8RKFGXWG0IML2OxAit/ZFRgZhMkhQ3d/bobQ== +diagnostic-channel@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/diagnostic-channel/-/diagnostic-channel-1.1.1.tgz#44b60972de9ee055c16216535b0e9db3f6a0efd0" + integrity sha512-r2HV5qFkUICyoaKlBEpLKHjxMXATUf/l+h8UZPGBHGLy4DDiY2sOLcIctax4eRnTw5wH2jTMExLntGPJ8eOJxw== dependencies: - semver "^5.3.0" + semver "^7.5.3" emitter-listener@^1.0.1, emitter-listener@^1.1.1: version "1.1.2" @@ -288,6 +404,18 @@ form-data@^4.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + http-proxy-agent@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz#5129800203520d434f142bc78ff3c170800f2b43" @@ -305,6 +433,30 @@ https-proxy-agent@^5.0.0: agent-base "6" debug "4" +import-in-the-middle@1.4.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/import-in-the-middle/-/import-in-the-middle-1.4.2.tgz#2a266676e3495e72c04bbaa5ec14756ba168391b" + integrity sha512-9WOz1Yh/cvO/p69sxRmhyQwrIGGSp7EIdcb+fFNVi7CzQGQB8U1/1XrKVSbEd/GNOAeM0peJtmi7+qphe7NvAw== + dependencies: + acorn "^8.8.2" + acorn-import-assertions "^1.9.0" + cjs-module-lexer "^1.2.2" + module-details-from-path "^1.0.3" + +is-core-module@^2.13.0: + version "2.13.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.0.tgz#bb52aa6e2cbd49a30c2ba68c42bf3435ba6072db" + integrity sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ== + dependencies: + has "^1.0.3" + +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + mime-db@1.52.0: version "1.52.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" @@ -317,17 +469,52 @@ mime-types@^2.1.12: dependencies: mime-db "1.52.0" +module-details-from-path@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/module-details-from-path/-/module-details-from-path-1.0.3.tgz#114c949673e2a8a35e9d35788527aa37b679da2b" + integrity sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A== + ms@2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +require-in-the-middle@^7.1.1: + version "7.2.0" + resolved "https://registry.yarnpkg.com/require-in-the-middle/-/require-in-the-middle-7.2.0.tgz#b539de8f00955444dc8aed95e17c69b0a4f10fcf" + integrity sha512-3TLx5TGyAY6AOqLBoXmHkNql0HIf2RGbuMgCDT2WO/uGVAPJs6h7Kl+bN6TIZGd9bWhWPwnDnTHGtW8Iu77sdw== + dependencies: + debug "^4.1.1" + module-details-from-path "^1.0.3" + resolve "^1.22.1" + +resolve@^1.22.1: + version "1.22.4" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.4.tgz#1dc40df46554cdaf8948a486a10f6ba1e2026c34" + integrity sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg== + dependencies: + is-core-module "^2.13.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + semver@^5.3.0, semver@^5.4.1: version "5.7.2" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== -shimmer@^1.1.0, shimmer@^1.2.0: +semver@^7.5.1, semver@^7.5.3: + version "7.5.4" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" + integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== + dependencies: + lru-cache "^6.0.0" + +shimmer@^1.1.0, shimmer@^1.2.0, shimmer@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/shimmer/-/shimmer-1.2.1.tgz#610859f7de327b587efebf501fb43117f9aff337" integrity sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw== @@ -337,6 +524,11 @@ stack-chain@^1.3.7: resolved "https://registry.yarnpkg.com/stack-chain/-/stack-chain-1.3.7.tgz#d192c9ff4ea6a22c94c4dd459171e3f00cea1285" integrity sha512-D8cWtWVdIe/jBA7v5p5Hwl5yOSOrmZPWDPe2KxQ5UAGD+nxbxU0lKXA4h85Ta6+qgdKVL3vUxsbIZjc1kBG7ug== +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + tslib@^2.2.0: version "2.4.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.1.tgz#0d0bfbaac2880b91e22df0768e55be9753a5b17e" @@ -346,3 +538,8 @@ uuid@^8.3.0: version "8.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== diff --git a/extensions/microsoft-authentication/package.json b/extensions/microsoft-authentication/package.json index c0ed977db77..8747c4a1df8 100644 --- a/extensions/microsoft-authentication/package.json +++ b/extensions/microsoft-authentication/package.json @@ -118,7 +118,7 @@ "dependencies": { "node-fetch": "2.6.7", "@azure/ms-rest-azure-env": "^2.0.0", - "@vscode/extension-telemetry": "0.7.5" + "@vscode/extension-telemetry": "^0.8.4" }, "repository": { "type": "git", diff --git a/extensions/microsoft-authentication/yarn.lock b/extensions/microsoft-authentication/yarn.lock index 13322694966..68b4aa00b84 100644 --- a/extensions/microsoft-authentication/yarn.lock +++ b/extensions/microsoft-authentication/yarn.lock @@ -17,7 +17,16 @@ "@azure/abort-controller" "^1.0.0" tslib "^2.2.0" -"@azure/core-rest-pipeline@^1.10.0": +"@azure/core-auth@^1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@azure/core-auth/-/core-auth-1.5.0.tgz#a41848c5c31cb3b7c84c409885267d55a2c92e44" + integrity sha512-udzoBuYG1VBoHVohDTrvKjyzel34zt77Bhp7dQntVGGD0ehVq48owENbBG8fIgkHRNUBQH5k1r0hpoMu5L8+kw== + dependencies: + "@azure/abort-controller" "^1.0.0" + "@azure/core-util" "^1.1.0" + tslib "^2.2.0" + +"@azure/core-rest-pipeline@1.10.1": version "1.10.1" resolved "https://registry.yarnpkg.com/@azure/core-rest-pipeline/-/core-rest-pipeline-1.10.1.tgz#348290847ca31b9eecf9cf5de7519aaccdd30968" integrity sha512-Kji9k6TOFRDB5ZMTw8qUf2IJ+CeJtsuMdAHox9eqpTf1cefiNMpzrfnF6sINEBZJsaVaWgQ0o48B6kcUH68niA== @@ -33,13 +42,21 @@ tslib "^2.2.0" uuid "^8.3.0" -"@azure/core-tracing@^1.0.1": +"@azure/core-tracing@^1.0.0", "@azure/core-tracing@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@azure/core-tracing/-/core-tracing-1.0.1.tgz#352a38cbea438c4a83c86b314f48017d70ba9503" integrity sha512-I5CGMoLtX+pI17ZdiFJZgxMJApsK6jjfm85hpgp3oazCdq5Wxgh4wMr7ge/TTWW1B5WBuvIOI1fMU/FrOAMKrw== dependencies: tslib "^2.2.0" +"@azure/core-util@1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@azure/core-util/-/core-util-1.2.0.tgz#3499deba1fc36dda6f1912b791809b6f15d4a392" + integrity sha512-ffGIw+Qs8bNKNLxz5UPkz4/VBM/EZY07mPve1ZYFqYUdPwFqRj0RPk0U7LZMOfT7GCck9YjuT1Rfp1PApNl1ng== + dependencies: + "@azure/abort-controller" "^1.0.0" + tslib "^2.2.0" + "@azure/core-util@^1.0.0": version "1.1.1" resolved "https://registry.yarnpkg.com/@azure/core-util/-/core-util-1.1.1.tgz#8f87b3dd468795df0f0849d9f096c3e7b29452c1" @@ -48,6 +65,14 @@ "@azure/abort-controller" "^1.0.0" tslib "^2.2.0" +"@azure/core-util@^1.1.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@azure/core-util/-/core-util-1.4.0.tgz#c120a56b3e48a9e4d20619a0b00268ae9de891c7" + integrity sha512-eGAyJpm3skVQoLiRqm/xPa+SXi/NPDdSHMxbRAz2lSprd+Zs+qrpQGQQ2VQ3Nttu+nSZR4XoYQC71LbEI7jsig== + dependencies: + "@azure/abort-controller" "^1.0.0" + tslib "^2.2.0" + "@azure/logger@^1.0.0": version "1.0.3" resolved "https://registry.yarnpkg.com/@azure/logger/-/logger-1.0.3.tgz#6e36704aa51be7d4a1bae24731ea580836293c96" @@ -60,66 +85,100 @@ resolved "https://registry.yarnpkg.com/@azure/ms-rest-azure-env/-/ms-rest-azure-env-2.0.0.tgz#45809f89763a480924e21d3c620cd40866771625" integrity sha512-dG76W7ElfLi+fbTjnZVGj+M9e0BIEJmRxU6fHaUQ12bZBe8EJKYb2GV50YWNaP2uJiVQ5+7nXEVj1VN1UQtaEw== -"@microsoft/1ds-core-js@3.2.8", "@microsoft/1ds-core-js@^3.2.8": - version "3.2.8" - resolved "https://registry.yarnpkg.com/@microsoft/1ds-core-js/-/1ds-core-js-3.2.8.tgz#1b6b7d9bb858238c818ccf4e4b58ece7aeae5760" - integrity sha512-9o9SUAamJiTXIYwpkQDuueYt83uZfXp8zp8YFix1IwVPwC9RmE36T2CX9gXOeq1nDckOuOduYpA8qHvdh5BGfQ== +"@azure/opentelemetry-instrumentation-azure-sdk@^1.0.0-beta.5": + version "1.0.0-beta.5" + resolved "https://registry.yarnpkg.com/@azure/opentelemetry-instrumentation-azure-sdk/-/opentelemetry-instrumentation-azure-sdk-1.0.0-beta.5.tgz#78809e6c005d08450701e5d37f087f6fce2f86eb" + integrity sha512-fsUarKQDvjhmBO4nIfaZkfNSApm1hZBzcvpNbSrXdcUBxu7lRvKsV5DnwszX7cnhLyVOW9yl1uigtRQ1yDANjA== dependencies: - "@microsoft/applicationinsights-core-js" "2.8.9" + "@azure/core-tracing" "^1.0.0" + "@azure/logger" "^1.0.0" + "@opentelemetry/api" "^1.4.1" + "@opentelemetry/core" "^1.15.2" + "@opentelemetry/instrumentation" "^0.41.2" + tslib "^2.2.0" + +"@microsoft/1ds-core-js@3.2.13", "@microsoft/1ds-core-js@^3.2.13": + version "3.2.13" + resolved "https://registry.yarnpkg.com/@microsoft/1ds-core-js/-/1ds-core-js-3.2.13.tgz#0c105ed75091bae3f1555c0334704fa9911c58fb" + integrity sha512-CluYTRWcEk0ObG5EWFNWhs87e2qchJUn0p2D21ZUa3PWojPZfPSBs4//WIE0MYV8Qg1Hdif2ZTwlM7TbYUjfAg== + dependencies: + "@microsoft/applicationinsights-core-js" "2.8.15" "@microsoft/applicationinsights-shims" "^2.0.2" "@microsoft/dynamicproto-js" "^1.1.7" -"@microsoft/1ds-post-js@^3.2.8": - version "3.2.8" - resolved "https://registry.yarnpkg.com/@microsoft/1ds-post-js/-/1ds-post-js-3.2.8.tgz#46793842cca161bf7a2a5b6053c349f429e55110" - integrity sha512-SjlRoNcXcXBH6WQD/5SkkaCHIVqldH3gDu+bI7YagrOVJ5APxwT1Duw9gm3L1FjFa9S2i81fvJ3EVSKpp9wULA== +"@microsoft/1ds-post-js@^3.2.13": + version "3.2.13" + resolved "https://registry.yarnpkg.com/@microsoft/1ds-post-js/-/1ds-post-js-3.2.13.tgz#560aacac8a92fdbb79e8c2ebcb293d56e19f51aa" + integrity sha512-HgS574fdD19Bo2vPguyznL4eDw7Pcm1cVNpvbvBLWiW3x4e1FCQ3VMXChWnAxCae8Hb0XqlA2sz332ZobBavTA== dependencies: - "@microsoft/1ds-core-js" "3.2.8" + "@microsoft/1ds-core-js" "3.2.13" "@microsoft/applicationinsights-shims" "^2.0.2" "@microsoft/dynamicproto-js" "^1.1.7" -"@microsoft/applicationinsights-channel-js@2.8.9": - version "2.8.9" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-channel-js/-/applicationinsights-channel-js-2.8.9.tgz#840656f3c716de8b3eb0a98c122aa1b92bb8ebfb" - integrity sha512-fMBsAEB7pWtPn43y72q9Xy5E5y55r6gMuDQqRRccccVoQDPXyS57VCj5IdATblctru0C6A8XpL2vRyNmEsu0Vg== +"@microsoft/applicationinsights-channel-js@3.0.2": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-channel-js/-/applicationinsights-channel-js-3.0.2.tgz#be49fbf74831c7b8c97950027c5052ea99d2a8a5" + integrity sha512-jDBNKbCHsJgmpv0CKNhJ/uN9ZphvfGdb93Svk+R4LjO8L3apNNMbDDPxBvXXi0uigRmA1TBcmyBG4IRKjabGhw== dependencies: - "@microsoft/applicationinsights-common" "2.8.9" - "@microsoft/applicationinsights-core-js" "2.8.9" - "@microsoft/applicationinsights-shims" "2.0.2" - "@microsoft/dynamicproto-js" "^1.1.7" + "@microsoft/applicationinsights-common" "3.0.2" + "@microsoft/applicationinsights-core-js" "3.0.2" + "@microsoft/applicationinsights-shims" "3.0.1" + "@microsoft/dynamicproto-js" "^2.0.2" + "@nevware21/ts-async" ">= 0.2.4 < 2.x" + "@nevware21/ts-utils" ">= 0.9.5 < 2.x" -"@microsoft/applicationinsights-common@2.8.9": - version "2.8.9" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-common/-/applicationinsights-common-2.8.9.tgz#a75e4a3143a7fd797687830c0ddd2069fd900827" - integrity sha512-mObn1moElyxZaGIRF/IU3cOaeKMgxghXnYEoHNUCA2e+rNwBIgxjyKkblFIpmGuHf4X7Oz3o3yBWpaC6AoMpig== +"@microsoft/applicationinsights-common@3.0.2": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-common/-/applicationinsights-common-3.0.2.tgz#37670bb07f4858ed41ff9759119e0759007d6e05" + integrity sha512-y+WXWop+OVim954Cu1uyYMnNx6PWO8okHpZIQi/1YSqtqaYdtJVPv4P0AVzwJdohxzVfgzKvqj9nec/VWqE2Zg== dependencies: - "@microsoft/applicationinsights-core-js" "2.8.9" - "@microsoft/applicationinsights-shims" "2.0.2" - "@microsoft/dynamicproto-js" "^1.1.7" + "@microsoft/applicationinsights-core-js" "3.0.2" + "@microsoft/applicationinsights-shims" "3.0.1" + "@microsoft/dynamicproto-js" "^2.0.2" + "@nevware21/ts-utils" ">= 0.9.5 < 2.x" -"@microsoft/applicationinsights-core-js@2.8.9": - version "2.8.9" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-2.8.9.tgz#0e5d207acfae6986a6fc97249eeb6117e523bf1b" - integrity sha512-HRuIuZ6aOWezcg/G5VyFDDWGL8hDNe/ljPP01J7ImH2kRPEgbtcfPSUMjkamGMefgdq81GZsSoC/NNGTP4pp2w== +"@microsoft/applicationinsights-core-js@2.8.15": + version "2.8.15" + resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-2.8.15.tgz#8fa466474260e01967fe649f14dd9e5ff91dcdc8" + integrity sha512-yYAs9MyjGr2YijQdUSN9mVgT1ijI1FPMgcffpaPmYbHAVbQmF7bXudrBWHxmLzJlwl5rfep+Zgjli2e67lwUqQ== dependencies: "@microsoft/applicationinsights-shims" "2.0.2" - "@microsoft/dynamicproto-js" "^1.1.7" + "@microsoft/dynamicproto-js" "^1.1.9" + +"@microsoft/applicationinsights-core-js@3.0.2": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-3.0.2.tgz#108e20df8c162bec92b1f66f9de2530a25d9f51a" + integrity sha512-WQhVhzlRlLDrQzn3OShCW/pL3BW5WC57t0oywSknX3q7lMzI3jDg7Ihh0iuIcNTzGCTbDkuqr4d6IjEDWIMtJQ== + dependencies: + "@microsoft/applicationinsights-shims" "3.0.1" + "@microsoft/dynamicproto-js" "^2.0.2" + "@nevware21/ts-async" ">= 0.2.4 < 2.x" + "@nevware21/ts-utils" ">= 0.9.5 < 2.x" "@microsoft/applicationinsights-shims@2.0.2", "@microsoft/applicationinsights-shims@^2.0.2": version "2.0.2" resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-shims/-/applicationinsights-shims-2.0.2.tgz#92b36a09375e2d9cb2b4203383b05772be837085" integrity sha512-PoHEgsnmcqruLNHZ/amACqdJ6YYQpED0KSRe6J7gIJTtpZC1FfFU9b1fmDKDKtFoUSrPzEh1qzO3kmRZP0betg== -"@microsoft/applicationinsights-web-basic@^2.8.9": - version "2.8.9" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-web-basic/-/applicationinsights-web-basic-2.8.9.tgz#eed2f3d1e19069962ed2155915c1656e6936e1d5" - integrity sha512-CH0J8JFOy7MjK8JO4pXXU+EML+Ilix+94PMZTX5EJlBU1in+mrik74/8qSg3UC4ekPi12KwrXaHCQSVC3WseXQ== +"@microsoft/applicationinsights-shims@3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-shims/-/applicationinsights-shims-3.0.1.tgz#3865b73ace8405b9c4618cc5c571f2fe3876f06f" + integrity sha512-DKwboF47H1nb33rSUfjqI6ryX29v+2QWcTrRvcQDA32AZr5Ilkr7whOOSsD1aBzwqX0RJEIP1Z81jfE3NBm/Lg== dependencies: - "@microsoft/applicationinsights-channel-js" "2.8.9" - "@microsoft/applicationinsights-common" "2.8.9" - "@microsoft/applicationinsights-core-js" "2.8.9" - "@microsoft/applicationinsights-shims" "2.0.2" - "@microsoft/dynamicproto-js" "^1.1.7" + "@nevware21/ts-utils" ">= 0.9.4 < 2.x" + +"@microsoft/applicationinsights-web-basic@^3.0.2": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-web-basic/-/applicationinsights-web-basic-3.0.2.tgz#f777a4d24b79dde3ae396d3b819e1fce06b7240a" + integrity sha512-6Lq0DE/pZp9RvSV+weGbcxN1NDmfczj6gNPhvZKV2YSQ3RK0LZE3+wjTWLXfuStq8a+nCBdsRpWk8tOKgsoxcg== + dependencies: + "@microsoft/applicationinsights-channel-js" "3.0.2" + "@microsoft/applicationinsights-common" "3.0.2" + "@microsoft/applicationinsights-core-js" "3.0.2" + "@microsoft/applicationinsights-shims" "3.0.1" + "@microsoft/dynamicproto-js" "^2.0.2" + "@nevware21/ts-async" ">= 0.2.4 < 2.x" + "@nevware21/ts-utils" ">= 0.9.5 < 2.x" "@microsoft/applicationinsights-web-snippet@^1.0.1": version "1.0.1" @@ -131,39 +190,74 @@ resolved "https://registry.yarnpkg.com/@microsoft/dynamicproto-js/-/dynamicproto-js-1.1.7.tgz#ede48dd3f85af14ee369c805e5ed5b84222b9fe2" integrity sha512-SK3D3aVt+5vOOccKPnGaJWB5gQ8FuKfjboUJHedMP7gu54HqSCXX5iFXhktGD8nfJb0Go30eDvs/UDoTnR2kOA== -"@opentelemetry/api@^1.0.4": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.2.0.tgz#89ef99401cde6208cff98760b67663726ef26686" - integrity sha512-0nBr+VZNKm9tvNDZFstI3Pq1fCTEDK5OZTnVKNvBNAKgd0yIvmwsP4m61rEv7ZP+tOUjWJhROpxK5MsnlF911g== +"@microsoft/dynamicproto-js@^1.1.9": + version "1.1.9" + resolved "https://registry.yarnpkg.com/@microsoft/dynamicproto-js/-/dynamicproto-js-1.1.9.tgz#7437db7aa061162ee94e4131b69a62b8dad5dea6" + integrity sha512-n1VPsljTSkthsAFYdiWfC+DKzK2WwcRp83Y1YAqdX552BstvsDjft9YXppjUzp11BPsapDoO1LDgrDB0XVsfNQ== -"@opentelemetry/core@1.7.0", "@opentelemetry/core@^1.0.1": - version "1.7.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-1.7.0.tgz#83bdd1b7a4ceafcdffd6590420657caec5f7b34c" - integrity sha512-AVqAi5uc8DrKJBimCTFUT4iFI+5eXpo4sYmGbQ0CypG0piOTHE2g9c5aSoTGYXu3CzOmJZf7pT6Xh+nwm5d6yQ== +"@microsoft/dynamicproto-js@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@microsoft/dynamicproto-js/-/dynamicproto-js-2.0.2.tgz#e57fbec2e7067d48b7e8e1e1c1d354028ef718a6" + integrity sha512-MB8trWaFREpmb037k/d0bB7T2BP7Ai24w1e1tbz3ASLB0/lwphsq3Nq8S9I5AsI5vs4zAQT+SB5nC5/dLYTiOg== dependencies: - "@opentelemetry/semantic-conventions" "1.7.0" + "@nevware21/ts-utils" ">= 0.9.4 < 2.x" -"@opentelemetry/resources@1.7.0": - version "1.7.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/resources/-/resources-1.7.0.tgz#90ccd3a6a86b4dfba4e833e73944bd64958d78c5" - integrity sha512-u1M0yZotkjyKx8dj+46Sg5thwtOTBmtRieNXqdCRiWUp6SfFiIP0bI+1XK3LhuXqXkBXA1awJZaTqKduNMStRg== +"@nevware21/ts-async@>= 0.2.4 < 2.x": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@nevware21/ts-async/-/ts-async-0.3.0.tgz#a8b97ba01065fc930de9a3f4dd4a05e862becc6c" + integrity sha512-ZUcgUH12LN/F6nzN0cYd0F/rJaMLmXr0EHVTyYfaYmK55bdwE4338uue4UiVoRqHVqNW4KDUrJc49iGogHKeWA== dependencies: - "@opentelemetry/core" "1.7.0" - "@opentelemetry/semantic-conventions" "1.7.0" + "@nevware21/ts-utils" ">= 0.10.0 < 2.x" -"@opentelemetry/sdk-trace-base@^1.0.1": - version "1.7.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.7.0.tgz#b498424e0c6340a9d80de63fd408c5c2130a60a5" - integrity sha512-Iz84C+FVOskmauh9FNnj4+VrA+hG5o+tkMzXuoesvSfunVSioXib0syVFeNXwOm4+M5GdWCuW632LVjqEXStIg== +"@nevware21/ts-utils@>= 0.10.0 < 2.x", "@nevware21/ts-utils@>= 0.9.4 < 2.x", "@nevware21/ts-utils@>= 0.9.5 < 2.x": + version "0.10.1" + resolved "https://registry.yarnpkg.com/@nevware21/ts-utils/-/ts-utils-0.10.1.tgz#aa65abc71eba06749a396598f22263d26f796ac7" + integrity sha512-pMny25NnF2/MJwdqC3Iyjm2pGIXNxni4AROpcqDeWa+td9JMUY4bUS9uU9XW+BoBRqTLUL+WURF9SOd/6OQzRg== + +"@opentelemetry/api@^1.4.1": + version "1.4.1" + resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.4.1.tgz#ff22eb2e5d476fbc2450a196e40dd243cc20c28f" + integrity sha512-O2yRJce1GOc6PAy3QxFM4NzFiWzvScDC1/5ihYBL6BUEVdq0XMWN01sppE+H6bBXbaFYipjwFLEWLg5PaSOThA== + +"@opentelemetry/core@1.15.2", "@opentelemetry/core@^1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-1.15.2.tgz#5b170bf223a2333884bbc2d29d95812cdbda7c9f" + integrity sha512-+gBv15ta96WqkHZaPpcDHiaz0utiiHZVfm2YOYSqFGrUaJpPkMoSuLBB58YFQGi6Rsb9EHos84X6X5+9JspmLw== dependencies: - "@opentelemetry/core" "1.7.0" - "@opentelemetry/resources" "1.7.0" - "@opentelemetry/semantic-conventions" "1.7.0" + "@opentelemetry/semantic-conventions" "1.15.2" -"@opentelemetry/semantic-conventions@1.7.0", "@opentelemetry/semantic-conventions@^1.0.1": - version "1.7.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.7.0.tgz#af80a1ef7cf110ea3a68242acd95648991bcd763" - integrity sha512-FGBx/Qd09lMaqQcogCHyYrFEpTx4cAjeS+48lMIR12z7LdH+zofGDVQSubN59nL6IpubfKqTeIDu9rNO28iHVA== +"@opentelemetry/instrumentation@^0.41.2": + version "0.41.2" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation/-/instrumentation-0.41.2.tgz#cae11fa64485dcf03dae331f35b315b64bc6189f" + integrity sha512-rxU72E0pKNH6ae2w5+xgVYZLzc5mlxAbGzF4shxMVK8YC2QQsfN38B2GPbj0jvrKWWNUElfclQ+YTykkNg/grw== + dependencies: + "@types/shimmer" "^1.0.2" + import-in-the-middle "1.4.2" + require-in-the-middle "^7.1.1" + semver "^7.5.1" + shimmer "^1.2.1" + +"@opentelemetry/resources@1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@opentelemetry/resources/-/resources-1.15.2.tgz#0c9e26cb65652a1402834a3c030cce6028d6dd9d" + integrity sha512-xmMRLenT9CXmm5HMbzpZ1hWhaUowQf8UB4jMjFlAxx1QzQcsD3KFNAVX/CAWzFPtllTyTplrA4JrQ7sCH3qmYw== + dependencies: + "@opentelemetry/core" "1.15.2" + "@opentelemetry/semantic-conventions" "1.15.2" + +"@opentelemetry/sdk-trace-base@^1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.15.2.tgz#4821f94033c55a6c8bbd35ae387b715b6108517a" + integrity sha512-BEaxGZbWtvnSPchV98qqqqa96AOcb41pjgvhfzDij10tkBhIu9m0Jd6tZ1tJB5ZHfHbTffqYVYE0AOGobec/EQ== + dependencies: + "@opentelemetry/core" "1.15.2" + "@opentelemetry/resources" "1.15.2" + "@opentelemetry/semantic-conventions" "1.15.2" + +"@opentelemetry/semantic-conventions@1.15.2", "@opentelemetry/semantic-conventions@^1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.15.2.tgz#3bafb5de3e20e841dff6cb3c66f4d6e9694c4241" + integrity sha512-CjbOKwk2s+3xPIMcd5UNYQzsf+v94RczbdNix9/kQh38WiQkM90sUOi3if8eyHFgiBjBjhwXrA7W3ydiSQP9mw== "@tootallnate/once@2": version "2.0.0" @@ -202,20 +296,35 @@ dependencies: "@types/node" "*" +"@types/shimmer@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@types/shimmer/-/shimmer-1.0.2.tgz#93eb2c243c351f3f17d5c580c7467ae5d686b65f" + integrity sha512-dKkr1bTxbEsFlh2ARpKzcaAmsYixqt9UyCdoEZk8rHyE4iQYcDCyvSjDSf7JUWJHlJiTtbIoQjxKh6ViywqDAg== + "@types/uuid@8.0.0": version "8.0.0" resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.0.0.tgz#165aae4819ad2174a17476dbe66feebd549556c0" integrity sha512-xSQfNcvOiE5f9dyd4Kzxbof1aTrLobL278pGLKOZI6esGfZ7ts9Ka16CzIN6Y8hFHE1C7jIBZokULhK1bOgjRw== -"@vscode/extension-telemetry@0.7.5": - version "0.7.5" - resolved "https://registry.yarnpkg.com/@vscode/extension-telemetry/-/extension-telemetry-0.7.5.tgz#bf965731816e08c3f146f96d901ec67954fc913b" - integrity sha512-fJ5y3TcpqqkFYHneabYaoB4XAhDdVflVm+TDKshw9VOs77jkgNS4UA7LNXrWeO0eDne3Sh3JgURf+xzc1rk69w== +"@vscode/extension-telemetry@^0.8.4": + version "0.8.4" + resolved "https://registry.yarnpkg.com/@vscode/extension-telemetry/-/extension-telemetry-0.8.4.tgz#c078c6f55df1c9e0592de3b4ce0f685dd345bfe7" + integrity sha512-UqM9+KZDDK3MyoHTsg6XNM+XO6pweQxzCpqJz33BoBEYAGsbBviRYcVpJglgay2oReuDD2pOI1Nio3BKNDLhWA== dependencies: - "@microsoft/1ds-core-js" "^3.2.8" - "@microsoft/1ds-post-js" "^3.2.8" - "@microsoft/applicationinsights-web-basic" "^2.8.9" - applicationinsights "2.4.1" + "@microsoft/1ds-core-js" "^3.2.13" + "@microsoft/1ds-post-js" "^3.2.13" + "@microsoft/applicationinsights-web-basic" "^3.0.2" + applicationinsights "^2.7.1" + +acorn-import-assertions@^1.9.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz#507276249d684797c84e0734ef84860334cfb1ac" + integrity sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA== + +acorn@^8.8.2: + version "8.10.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5" + integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw== agent-base@6: version "6.0.2" @@ -224,22 +333,24 @@ agent-base@6: dependencies: debug "4" -applicationinsights@2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/applicationinsights/-/applicationinsights-2.4.1.tgz#4de4c4dd3c7c4a44445cfbf3d15808fc0dcc423d" - integrity sha512-0n0Ikd0gzSm460xm+M0UTWIwXrhrH/0bqfZatcJjYObWyefxfAxapGEyNnSGd1Tg90neHz+Yhf+Ff/zgvPiQYA== +applicationinsights@^2.7.1: + version "2.7.3" + resolved "https://registry.yarnpkg.com/applicationinsights/-/applicationinsights-2.7.3.tgz#8781454d29c0b14c9773f2e892b4cf5e7468ffa5" + integrity sha512-JY8+kTEkjbA+kAVNWDtpfW2lqsrDALfDXuxOs74KLPu2y13fy/9WB52V4LfYVTVcW1/jYOXjTxNS2gPZIDh1iw== dependencies: - "@azure/core-auth" "^1.4.0" - "@azure/core-rest-pipeline" "^1.10.0" + "@azure/core-auth" "^1.5.0" + "@azure/core-rest-pipeline" "1.10.1" + "@azure/core-util" "1.2.0" + "@azure/opentelemetry-instrumentation-azure-sdk" "^1.0.0-beta.5" "@microsoft/applicationinsights-web-snippet" "^1.0.1" - "@opentelemetry/api" "^1.0.4" - "@opentelemetry/core" "^1.0.1" - "@opentelemetry/sdk-trace-base" "^1.0.1" - "@opentelemetry/semantic-conventions" "^1.0.1" + "@opentelemetry/api" "^1.4.1" + "@opentelemetry/core" "^1.15.2" + "@opentelemetry/sdk-trace-base" "^1.15.2" + "@opentelemetry/semantic-conventions" "^1.15.2" cls-hooked "^4.2.2" continuation-local-storage "^3.2.1" - diagnostic-channel "1.1.0" - diagnostic-channel-publishers "1.0.5" + diagnostic-channel "1.1.1" + diagnostic-channel-publishers "1.0.7" async-hook-jl@^1.7.6: version "1.7.6" @@ -261,6 +372,11 @@ asynckit@^0.4.0: resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= +cjs-module-lexer@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz#6c370ab19f8a3394e318fe682686ec0ac684d107" + integrity sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ== + cls-hooked@^4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/cls-hooked/-/cls-hooked-4.2.2.tgz#ad2e9a4092680cdaffeb2d3551da0e225eae1908" @@ -285,7 +401,7 @@ continuation-local-storage@^3.2.1: async-listener "^0.6.0" emitter-listener "^1.1.1" -debug@4: +debug@4, debug@^4.1.1: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== @@ -297,17 +413,17 @@ delayed-stream@~1.0.0: resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= -diagnostic-channel-publishers@1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/diagnostic-channel-publishers/-/diagnostic-channel-publishers-1.0.5.tgz#df8c317086c50f5727fdfb5d2fce214d2e4130ae" - integrity sha512-dJwUS0915pkjjimPJVDnS/QQHsH0aOYhnZsLJdnZIMOrB+csj8RnZhWTuwnm8R5v3Z7OZs+ksv5luC14DGB7eg== +diagnostic-channel-publishers@1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/diagnostic-channel-publishers/-/diagnostic-channel-publishers-1.0.7.tgz#9b7f8d5ee1295481aee19c827d917e96fedf2c4a" + integrity sha512-SEECbY5AiVt6DfLkhkaHNeshg1CogdLLANA8xlG/TKvS+XUgvIKl7VspJGYiEdL5OUyzMVnr7o0AwB7f+/Mjtg== -diagnostic-channel@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/diagnostic-channel/-/diagnostic-channel-1.1.0.tgz#6985e9dfedfbc072d91dc4388477e4087147756e" - integrity sha512-fwujyMe1gj6rk6dYi9hMZm0c8Mz8NDMVl2LB4iaYh3+LIAThZC8RKFGXWG0IML2OxAit/ZFRgZhMkhQ3d/bobQ== +diagnostic-channel@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/diagnostic-channel/-/diagnostic-channel-1.1.1.tgz#44b60972de9ee055c16216535b0e9db3f6a0efd0" + integrity sha512-r2HV5qFkUICyoaKlBEpLKHjxMXATUf/l+h8UZPGBHGLy4DDiY2sOLcIctax4eRnTw5wH2jTMExLntGPJ8eOJxw== dependencies: - semver "^5.3.0" + semver "^7.5.3" emitter-listener@^1.0.1, emitter-listener@^1.1.1: version "1.1.2" @@ -334,6 +450,18 @@ form-data@^4.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + http-proxy-agent@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz#5129800203520d434f142bc78ff3c170800f2b43" @@ -351,6 +479,30 @@ https-proxy-agent@^5.0.0: agent-base "6" debug "4" +import-in-the-middle@1.4.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/import-in-the-middle/-/import-in-the-middle-1.4.2.tgz#2a266676e3495e72c04bbaa5ec14756ba168391b" + integrity sha512-9WOz1Yh/cvO/p69sxRmhyQwrIGGSp7EIdcb+fFNVi7CzQGQB8U1/1XrKVSbEd/GNOAeM0peJtmi7+qphe7NvAw== + dependencies: + acorn "^8.8.2" + acorn-import-assertions "^1.9.0" + cjs-module-lexer "^1.2.2" + module-details-from-path "^1.0.3" + +is-core-module@^2.13.0: + version "2.13.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.0.tgz#bb52aa6e2cbd49a30c2ba68c42bf3435ba6072db" + integrity sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ== + dependencies: + has "^1.0.3" + +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + mime-db@1.44.0: version "1.44.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.44.0.tgz#fa11c5eb0aca1334b4233cb4d52f10c5a6272f92" @@ -363,6 +515,11 @@ mime-types@^2.1.12: dependencies: mime-db "1.44.0" +module-details-from-path@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/module-details-from-path/-/module-details-from-path-1.0.3.tgz#114c949673e2a8a35e9d35788527aa37b679da2b" + integrity sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A== + ms@2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" @@ -375,12 +532,42 @@ node-fetch@2.6.7: dependencies: whatwg-url "^5.0.0" +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +require-in-the-middle@^7.1.1: + version "7.2.0" + resolved "https://registry.yarnpkg.com/require-in-the-middle/-/require-in-the-middle-7.2.0.tgz#b539de8f00955444dc8aed95e17c69b0a4f10fcf" + integrity sha512-3TLx5TGyAY6AOqLBoXmHkNql0HIf2RGbuMgCDT2WO/uGVAPJs6h7Kl+bN6TIZGd9bWhWPwnDnTHGtW8Iu77sdw== + dependencies: + debug "^4.1.1" + module-details-from-path "^1.0.3" + resolve "^1.22.1" + +resolve@^1.22.1: + version "1.22.4" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.4.tgz#1dc40df46554cdaf8948a486a10f6ba1e2026c34" + integrity sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg== + dependencies: + is-core-module "^2.13.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + semver@^5.3.0, semver@^5.4.1: version "5.7.2" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== -shimmer@^1.1.0, shimmer@^1.2.0: +semver@^7.5.1, semver@^7.5.3: + version "7.5.4" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" + integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== + dependencies: + lru-cache "^6.0.0" + +shimmer@^1.1.0, shimmer@^1.2.0, shimmer@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/shimmer/-/shimmer-1.2.1.tgz#610859f7de327b587efebf501fb43117f9aff337" integrity sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw== @@ -390,6 +577,11 @@ stack-chain@^1.3.7: resolved "https://registry.yarnpkg.com/stack-chain/-/stack-chain-1.3.7.tgz#d192c9ff4ea6a22c94c4dd459171e3f00cea1285" integrity sha512-D8cWtWVdIe/jBA7v5p5Hwl5yOSOrmZPWDPe2KxQ5UAGD+nxbxU0lKXA4h85Ta6+qgdKVL3vUxsbIZjc1kBG7ug== +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + tr46@~0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" @@ -417,3 +609,8 @@ whatwg-url@^5.0.0: dependencies: tr46 "~0.0.3" webidl-conversions "^3.0.0" + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== diff --git a/extensions/shared.webpack.config.js b/extensions/shared.webpack.config.js index 5a9ccd93d30..cd9aef49677 100644 --- a/extensions/shared.webpack.config.js +++ b/extensions/shared.webpack.config.js @@ -60,6 +60,7 @@ function withNodeDefaults(/**@type WebpackConfig & { context: string }*/extConfi externals: { 'vscode': 'commonjs vscode', // ignored because it doesn't exist, 'applicationinsights-native-metrics': 'commonjs applicationinsights-native-metrics', // ignored because we don't ship native module + '@azure/functions-core': 'commonjs azure/functions-core', // optioinal dependency of appinsights that we don't use '@opentelemetry/tracing': 'commonjs @opentelemetry/tracing', // ignored because we don't ship this module '@opentelemetry/instrumentation': 'commonjs @opentelemetry/instrumentation', // ignored because we don't ship this module '@azure/opentelemetry-instrumentation-azure-sdk': 'commonjs @azure/opentelemetry-instrumentation-azure-sdk', // ignored because we don't ship this module @@ -143,6 +144,7 @@ function withBrowserDefaults(/**@type WebpackConfig & { context: string }*/extCo externals: { 'vscode': 'commonjs vscode', // ignored because it doesn't exist, 'applicationinsights-native-metrics': 'commonjs applicationinsights-native-metrics', // ignored because we don't ship native module + '@azure/functions-core': 'commonjs azure/functions-core', // optioinal dependency of appinsights that we don't use '@opentelemetry/tracing': 'commonjs @opentelemetry/tracing', // ignored because we don't ship this module '@opentelemetry/instrumentation': 'commonjs @opentelemetry/instrumentation', // ignored because we don't ship this module '@azure/opentelemetry-instrumentation-azure-sdk': 'commonjs @azure/opentelemetry-instrumentation-azure-sdk', // ignored because we don't ship this module diff --git a/extensions/simple-browser/package.json b/extensions/simple-browser/package.json index 79abe8e57cd..e86b8de070b 100644 --- a/extensions/simple-browser/package.json +++ b/extensions/simple-browser/package.json @@ -66,7 +66,7 @@ "watch-web": "npx webpack-cli --config extension-browser.webpack.config --mode none --watch --info-verbosity verbose" }, "dependencies": { - "@vscode/extension-telemetry": "0.7.5" + "@vscode/extension-telemetry": "^0.8.4" }, "devDependencies": { "@types/vscode-webview": "^1.57.0", diff --git a/extensions/simple-browser/yarn.lock b/extensions/simple-browser/yarn.lock index e57ce16ff44..d6ce34c9e21 100644 --- a/extensions/simple-browser/yarn.lock +++ b/extensions/simple-browser/yarn.lock @@ -17,7 +17,16 @@ "@azure/abort-controller" "^1.0.0" tslib "^2.2.0" -"@azure/core-rest-pipeline@^1.10.0": +"@azure/core-auth@^1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@azure/core-auth/-/core-auth-1.5.0.tgz#a41848c5c31cb3b7c84c409885267d55a2c92e44" + integrity sha512-udzoBuYG1VBoHVohDTrvKjyzel34zt77Bhp7dQntVGGD0ehVq48owENbBG8fIgkHRNUBQH5k1r0hpoMu5L8+kw== + dependencies: + "@azure/abort-controller" "^1.0.0" + "@azure/core-util" "^1.1.0" + tslib "^2.2.0" + +"@azure/core-rest-pipeline@1.10.1": version "1.10.1" resolved "https://registry.yarnpkg.com/@azure/core-rest-pipeline/-/core-rest-pipeline-1.10.1.tgz#348290847ca31b9eecf9cf5de7519aaccdd30968" integrity sha512-Kji9k6TOFRDB5ZMTw8qUf2IJ+CeJtsuMdAHox9eqpTf1cefiNMpzrfnF6sINEBZJsaVaWgQ0o48B6kcUH68niA== @@ -33,13 +42,21 @@ tslib "^2.2.0" uuid "^8.3.0" -"@azure/core-tracing@^1.0.1": +"@azure/core-tracing@^1.0.0", "@azure/core-tracing@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@azure/core-tracing/-/core-tracing-1.0.1.tgz#352a38cbea438c4a83c86b314f48017d70ba9503" integrity sha512-I5CGMoLtX+pI17ZdiFJZgxMJApsK6jjfm85hpgp3oazCdq5Wxgh4wMr7ge/TTWW1B5WBuvIOI1fMU/FrOAMKrw== dependencies: tslib "^2.2.0" +"@azure/core-util@1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@azure/core-util/-/core-util-1.2.0.tgz#3499deba1fc36dda6f1912b791809b6f15d4a392" + integrity sha512-ffGIw+Qs8bNKNLxz5UPkz4/VBM/EZY07mPve1ZYFqYUdPwFqRj0RPk0U7LZMOfT7GCck9YjuT1Rfp1PApNl1ng== + dependencies: + "@azure/abort-controller" "^1.0.0" + tslib "^2.2.0" + "@azure/core-util@^1.0.0": version "1.1.1" resolved "https://registry.yarnpkg.com/@azure/core-util/-/core-util-1.1.1.tgz#8f87b3dd468795df0f0849d9f096c3e7b29452c1" @@ -48,6 +65,14 @@ "@azure/abort-controller" "^1.0.0" tslib "^2.2.0" +"@azure/core-util@^1.1.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@azure/core-util/-/core-util-1.4.0.tgz#c120a56b3e48a9e4d20619a0b00268ae9de891c7" + integrity sha512-eGAyJpm3skVQoLiRqm/xPa+SXi/NPDdSHMxbRAz2lSprd+Zs+qrpQGQQ2VQ3Nttu+nSZR4XoYQC71LbEI7jsig== + dependencies: + "@azure/abort-controller" "^1.0.0" + tslib "^2.2.0" + "@azure/logger@^1.0.0": version "1.0.3" resolved "https://registry.yarnpkg.com/@azure/logger/-/logger-1.0.3.tgz#6e36704aa51be7d4a1bae24731ea580836293c96" @@ -55,66 +80,100 @@ dependencies: tslib "^2.2.0" -"@microsoft/1ds-core-js@3.2.8", "@microsoft/1ds-core-js@^3.2.8": - version "3.2.8" - resolved "https://registry.yarnpkg.com/@microsoft/1ds-core-js/-/1ds-core-js-3.2.8.tgz#1b6b7d9bb858238c818ccf4e4b58ece7aeae5760" - integrity sha512-9o9SUAamJiTXIYwpkQDuueYt83uZfXp8zp8YFix1IwVPwC9RmE36T2CX9gXOeq1nDckOuOduYpA8qHvdh5BGfQ== +"@azure/opentelemetry-instrumentation-azure-sdk@^1.0.0-beta.5": + version "1.0.0-beta.5" + resolved "https://registry.yarnpkg.com/@azure/opentelemetry-instrumentation-azure-sdk/-/opentelemetry-instrumentation-azure-sdk-1.0.0-beta.5.tgz#78809e6c005d08450701e5d37f087f6fce2f86eb" + integrity sha512-fsUarKQDvjhmBO4nIfaZkfNSApm1hZBzcvpNbSrXdcUBxu7lRvKsV5DnwszX7cnhLyVOW9yl1uigtRQ1yDANjA== dependencies: - "@microsoft/applicationinsights-core-js" "2.8.9" + "@azure/core-tracing" "^1.0.0" + "@azure/logger" "^1.0.0" + "@opentelemetry/api" "^1.4.1" + "@opentelemetry/core" "^1.15.2" + "@opentelemetry/instrumentation" "^0.41.2" + tslib "^2.2.0" + +"@microsoft/1ds-core-js@3.2.13", "@microsoft/1ds-core-js@^3.2.13": + version "3.2.13" + resolved "https://registry.yarnpkg.com/@microsoft/1ds-core-js/-/1ds-core-js-3.2.13.tgz#0c105ed75091bae3f1555c0334704fa9911c58fb" + integrity sha512-CluYTRWcEk0ObG5EWFNWhs87e2qchJUn0p2D21ZUa3PWojPZfPSBs4//WIE0MYV8Qg1Hdif2ZTwlM7TbYUjfAg== + dependencies: + "@microsoft/applicationinsights-core-js" "2.8.15" "@microsoft/applicationinsights-shims" "^2.0.2" "@microsoft/dynamicproto-js" "^1.1.7" -"@microsoft/1ds-post-js@^3.2.8": - version "3.2.8" - resolved "https://registry.yarnpkg.com/@microsoft/1ds-post-js/-/1ds-post-js-3.2.8.tgz#46793842cca161bf7a2a5b6053c349f429e55110" - integrity sha512-SjlRoNcXcXBH6WQD/5SkkaCHIVqldH3gDu+bI7YagrOVJ5APxwT1Duw9gm3L1FjFa9S2i81fvJ3EVSKpp9wULA== +"@microsoft/1ds-post-js@^3.2.13": + version "3.2.13" + resolved "https://registry.yarnpkg.com/@microsoft/1ds-post-js/-/1ds-post-js-3.2.13.tgz#560aacac8a92fdbb79e8c2ebcb293d56e19f51aa" + integrity sha512-HgS574fdD19Bo2vPguyznL4eDw7Pcm1cVNpvbvBLWiW3x4e1FCQ3VMXChWnAxCae8Hb0XqlA2sz332ZobBavTA== dependencies: - "@microsoft/1ds-core-js" "3.2.8" + "@microsoft/1ds-core-js" "3.2.13" "@microsoft/applicationinsights-shims" "^2.0.2" "@microsoft/dynamicproto-js" "^1.1.7" -"@microsoft/applicationinsights-channel-js@2.8.9": - version "2.8.9" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-channel-js/-/applicationinsights-channel-js-2.8.9.tgz#840656f3c716de8b3eb0a98c122aa1b92bb8ebfb" - integrity sha512-fMBsAEB7pWtPn43y72q9Xy5E5y55r6gMuDQqRRccccVoQDPXyS57VCj5IdATblctru0C6A8XpL2vRyNmEsu0Vg== +"@microsoft/applicationinsights-channel-js@3.0.2": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-channel-js/-/applicationinsights-channel-js-3.0.2.tgz#be49fbf74831c7b8c97950027c5052ea99d2a8a5" + integrity sha512-jDBNKbCHsJgmpv0CKNhJ/uN9ZphvfGdb93Svk+R4LjO8L3apNNMbDDPxBvXXi0uigRmA1TBcmyBG4IRKjabGhw== dependencies: - "@microsoft/applicationinsights-common" "2.8.9" - "@microsoft/applicationinsights-core-js" "2.8.9" - "@microsoft/applicationinsights-shims" "2.0.2" - "@microsoft/dynamicproto-js" "^1.1.7" + "@microsoft/applicationinsights-common" "3.0.2" + "@microsoft/applicationinsights-core-js" "3.0.2" + "@microsoft/applicationinsights-shims" "3.0.1" + "@microsoft/dynamicproto-js" "^2.0.2" + "@nevware21/ts-async" ">= 0.2.4 < 2.x" + "@nevware21/ts-utils" ">= 0.9.5 < 2.x" -"@microsoft/applicationinsights-common@2.8.9": - version "2.8.9" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-common/-/applicationinsights-common-2.8.9.tgz#a75e4a3143a7fd797687830c0ddd2069fd900827" - integrity sha512-mObn1moElyxZaGIRF/IU3cOaeKMgxghXnYEoHNUCA2e+rNwBIgxjyKkblFIpmGuHf4X7Oz3o3yBWpaC6AoMpig== +"@microsoft/applicationinsights-common@3.0.2": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-common/-/applicationinsights-common-3.0.2.tgz#37670bb07f4858ed41ff9759119e0759007d6e05" + integrity sha512-y+WXWop+OVim954Cu1uyYMnNx6PWO8okHpZIQi/1YSqtqaYdtJVPv4P0AVzwJdohxzVfgzKvqj9nec/VWqE2Zg== dependencies: - "@microsoft/applicationinsights-core-js" "2.8.9" - "@microsoft/applicationinsights-shims" "2.0.2" - "@microsoft/dynamicproto-js" "^1.1.7" + "@microsoft/applicationinsights-core-js" "3.0.2" + "@microsoft/applicationinsights-shims" "3.0.1" + "@microsoft/dynamicproto-js" "^2.0.2" + "@nevware21/ts-utils" ">= 0.9.5 < 2.x" -"@microsoft/applicationinsights-core-js@2.8.9": - version "2.8.9" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-2.8.9.tgz#0e5d207acfae6986a6fc97249eeb6117e523bf1b" - integrity sha512-HRuIuZ6aOWezcg/G5VyFDDWGL8hDNe/ljPP01J7ImH2kRPEgbtcfPSUMjkamGMefgdq81GZsSoC/NNGTP4pp2w== +"@microsoft/applicationinsights-core-js@2.8.15": + version "2.8.15" + resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-2.8.15.tgz#8fa466474260e01967fe649f14dd9e5ff91dcdc8" + integrity sha512-yYAs9MyjGr2YijQdUSN9mVgT1ijI1FPMgcffpaPmYbHAVbQmF7bXudrBWHxmLzJlwl5rfep+Zgjli2e67lwUqQ== dependencies: "@microsoft/applicationinsights-shims" "2.0.2" - "@microsoft/dynamicproto-js" "^1.1.7" + "@microsoft/dynamicproto-js" "^1.1.9" + +"@microsoft/applicationinsights-core-js@3.0.2": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-3.0.2.tgz#108e20df8c162bec92b1f66f9de2530a25d9f51a" + integrity sha512-WQhVhzlRlLDrQzn3OShCW/pL3BW5WC57t0oywSknX3q7lMzI3jDg7Ihh0iuIcNTzGCTbDkuqr4d6IjEDWIMtJQ== + dependencies: + "@microsoft/applicationinsights-shims" "3.0.1" + "@microsoft/dynamicproto-js" "^2.0.2" + "@nevware21/ts-async" ">= 0.2.4 < 2.x" + "@nevware21/ts-utils" ">= 0.9.5 < 2.x" "@microsoft/applicationinsights-shims@2.0.2", "@microsoft/applicationinsights-shims@^2.0.2": version "2.0.2" resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-shims/-/applicationinsights-shims-2.0.2.tgz#92b36a09375e2d9cb2b4203383b05772be837085" integrity sha512-PoHEgsnmcqruLNHZ/amACqdJ6YYQpED0KSRe6J7gIJTtpZC1FfFU9b1fmDKDKtFoUSrPzEh1qzO3kmRZP0betg== -"@microsoft/applicationinsights-web-basic@^2.8.9": - version "2.8.9" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-web-basic/-/applicationinsights-web-basic-2.8.9.tgz#eed2f3d1e19069962ed2155915c1656e6936e1d5" - integrity sha512-CH0J8JFOy7MjK8JO4pXXU+EML+Ilix+94PMZTX5EJlBU1in+mrik74/8qSg3UC4ekPi12KwrXaHCQSVC3WseXQ== +"@microsoft/applicationinsights-shims@3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-shims/-/applicationinsights-shims-3.0.1.tgz#3865b73ace8405b9c4618cc5c571f2fe3876f06f" + integrity sha512-DKwboF47H1nb33rSUfjqI6ryX29v+2QWcTrRvcQDA32AZr5Ilkr7whOOSsD1aBzwqX0RJEIP1Z81jfE3NBm/Lg== dependencies: - "@microsoft/applicationinsights-channel-js" "2.8.9" - "@microsoft/applicationinsights-common" "2.8.9" - "@microsoft/applicationinsights-core-js" "2.8.9" - "@microsoft/applicationinsights-shims" "2.0.2" - "@microsoft/dynamicproto-js" "^1.1.7" + "@nevware21/ts-utils" ">= 0.9.4 < 2.x" + +"@microsoft/applicationinsights-web-basic@^3.0.2": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-web-basic/-/applicationinsights-web-basic-3.0.2.tgz#f777a4d24b79dde3ae396d3b819e1fce06b7240a" + integrity sha512-6Lq0DE/pZp9RvSV+weGbcxN1NDmfczj6gNPhvZKV2YSQ3RK0LZE3+wjTWLXfuStq8a+nCBdsRpWk8tOKgsoxcg== + dependencies: + "@microsoft/applicationinsights-channel-js" "3.0.2" + "@microsoft/applicationinsights-common" "3.0.2" + "@microsoft/applicationinsights-core-js" "3.0.2" + "@microsoft/applicationinsights-shims" "3.0.1" + "@microsoft/dynamicproto-js" "^2.0.2" + "@nevware21/ts-async" ">= 0.2.4 < 2.x" + "@nevware21/ts-utils" ">= 0.9.5 < 2.x" "@microsoft/applicationinsights-web-snippet@^1.0.1": version "1.0.1" @@ -126,59 +185,109 @@ resolved "https://registry.yarnpkg.com/@microsoft/dynamicproto-js/-/dynamicproto-js-1.1.7.tgz#ede48dd3f85af14ee369c805e5ed5b84222b9fe2" integrity sha512-SK3D3aVt+5vOOccKPnGaJWB5gQ8FuKfjboUJHedMP7gu54HqSCXX5iFXhktGD8nfJb0Go30eDvs/UDoTnR2kOA== -"@opentelemetry/api@^1.0.4": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.2.0.tgz#89ef99401cde6208cff98760b67663726ef26686" - integrity sha512-0nBr+VZNKm9tvNDZFstI3Pq1fCTEDK5OZTnVKNvBNAKgd0yIvmwsP4m61rEv7ZP+tOUjWJhROpxK5MsnlF911g== +"@microsoft/dynamicproto-js@^1.1.9": + version "1.1.9" + resolved "https://registry.yarnpkg.com/@microsoft/dynamicproto-js/-/dynamicproto-js-1.1.9.tgz#7437db7aa061162ee94e4131b69a62b8dad5dea6" + integrity sha512-n1VPsljTSkthsAFYdiWfC+DKzK2WwcRp83Y1YAqdX552BstvsDjft9YXppjUzp11BPsapDoO1LDgrDB0XVsfNQ== -"@opentelemetry/core@1.7.0", "@opentelemetry/core@^1.0.1": - version "1.7.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-1.7.0.tgz#83bdd1b7a4ceafcdffd6590420657caec5f7b34c" - integrity sha512-AVqAi5uc8DrKJBimCTFUT4iFI+5eXpo4sYmGbQ0CypG0piOTHE2g9c5aSoTGYXu3CzOmJZf7pT6Xh+nwm5d6yQ== +"@microsoft/dynamicproto-js@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@microsoft/dynamicproto-js/-/dynamicproto-js-2.0.2.tgz#e57fbec2e7067d48b7e8e1e1c1d354028ef718a6" + integrity sha512-MB8trWaFREpmb037k/d0bB7T2BP7Ai24w1e1tbz3ASLB0/lwphsq3Nq8S9I5AsI5vs4zAQT+SB5nC5/dLYTiOg== dependencies: - "@opentelemetry/semantic-conventions" "1.7.0" + "@nevware21/ts-utils" ">= 0.9.4 < 2.x" -"@opentelemetry/resources@1.7.0": - version "1.7.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/resources/-/resources-1.7.0.tgz#90ccd3a6a86b4dfba4e833e73944bd64958d78c5" - integrity sha512-u1M0yZotkjyKx8dj+46Sg5thwtOTBmtRieNXqdCRiWUp6SfFiIP0bI+1XK3LhuXqXkBXA1awJZaTqKduNMStRg== +"@nevware21/ts-async@>= 0.2.4 < 2.x": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@nevware21/ts-async/-/ts-async-0.3.0.tgz#a8b97ba01065fc930de9a3f4dd4a05e862becc6c" + integrity sha512-ZUcgUH12LN/F6nzN0cYd0F/rJaMLmXr0EHVTyYfaYmK55bdwE4338uue4UiVoRqHVqNW4KDUrJc49iGogHKeWA== dependencies: - "@opentelemetry/core" "1.7.0" - "@opentelemetry/semantic-conventions" "1.7.0" + "@nevware21/ts-utils" ">= 0.10.0 < 2.x" -"@opentelemetry/sdk-trace-base@^1.0.1": - version "1.7.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.7.0.tgz#b498424e0c6340a9d80de63fd408c5c2130a60a5" - integrity sha512-Iz84C+FVOskmauh9FNnj4+VrA+hG5o+tkMzXuoesvSfunVSioXib0syVFeNXwOm4+M5GdWCuW632LVjqEXStIg== +"@nevware21/ts-utils@>= 0.10.0 < 2.x", "@nevware21/ts-utils@>= 0.9.4 < 2.x", "@nevware21/ts-utils@>= 0.9.5 < 2.x": + version "0.10.1" + resolved "https://registry.yarnpkg.com/@nevware21/ts-utils/-/ts-utils-0.10.1.tgz#aa65abc71eba06749a396598f22263d26f796ac7" + integrity sha512-pMny25NnF2/MJwdqC3Iyjm2pGIXNxni4AROpcqDeWa+td9JMUY4bUS9uU9XW+BoBRqTLUL+WURF9SOd/6OQzRg== + +"@opentelemetry/api@^1.4.1": + version "1.4.1" + resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.4.1.tgz#ff22eb2e5d476fbc2450a196e40dd243cc20c28f" + integrity sha512-O2yRJce1GOc6PAy3QxFM4NzFiWzvScDC1/5ihYBL6BUEVdq0XMWN01sppE+H6bBXbaFYipjwFLEWLg5PaSOThA== + +"@opentelemetry/core@1.15.2", "@opentelemetry/core@^1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-1.15.2.tgz#5b170bf223a2333884bbc2d29d95812cdbda7c9f" + integrity sha512-+gBv15ta96WqkHZaPpcDHiaz0utiiHZVfm2YOYSqFGrUaJpPkMoSuLBB58YFQGi6Rsb9EHos84X6X5+9JspmLw== dependencies: - "@opentelemetry/core" "1.7.0" - "@opentelemetry/resources" "1.7.0" - "@opentelemetry/semantic-conventions" "1.7.0" + "@opentelemetry/semantic-conventions" "1.15.2" -"@opentelemetry/semantic-conventions@1.7.0", "@opentelemetry/semantic-conventions@^1.0.1": - version "1.7.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.7.0.tgz#af80a1ef7cf110ea3a68242acd95648991bcd763" - integrity sha512-FGBx/Qd09lMaqQcogCHyYrFEpTx4cAjeS+48lMIR12z7LdH+zofGDVQSubN59nL6IpubfKqTeIDu9rNO28iHVA== +"@opentelemetry/instrumentation@^0.41.2": + version "0.41.2" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation/-/instrumentation-0.41.2.tgz#cae11fa64485dcf03dae331f35b315b64bc6189f" + integrity sha512-rxU72E0pKNH6ae2w5+xgVYZLzc5mlxAbGzF4shxMVK8YC2QQsfN38B2GPbj0jvrKWWNUElfclQ+YTykkNg/grw== + dependencies: + "@types/shimmer" "^1.0.2" + import-in-the-middle "1.4.2" + require-in-the-middle "^7.1.1" + semver "^7.5.1" + shimmer "^1.2.1" + +"@opentelemetry/resources@1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@opentelemetry/resources/-/resources-1.15.2.tgz#0c9e26cb65652a1402834a3c030cce6028d6dd9d" + integrity sha512-xmMRLenT9CXmm5HMbzpZ1hWhaUowQf8UB4jMjFlAxx1QzQcsD3KFNAVX/CAWzFPtllTyTplrA4JrQ7sCH3qmYw== + dependencies: + "@opentelemetry/core" "1.15.2" + "@opentelemetry/semantic-conventions" "1.15.2" + +"@opentelemetry/sdk-trace-base@^1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.15.2.tgz#4821f94033c55a6c8bbd35ae387b715b6108517a" + integrity sha512-BEaxGZbWtvnSPchV98qqqqa96AOcb41pjgvhfzDij10tkBhIu9m0Jd6tZ1tJB5ZHfHbTffqYVYE0AOGobec/EQ== + dependencies: + "@opentelemetry/core" "1.15.2" + "@opentelemetry/resources" "1.15.2" + "@opentelemetry/semantic-conventions" "1.15.2" + +"@opentelemetry/semantic-conventions@1.15.2", "@opentelemetry/semantic-conventions@^1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.15.2.tgz#3bafb5de3e20e841dff6cb3c66f4d6e9694c4241" + integrity sha512-CjbOKwk2s+3xPIMcd5UNYQzsf+v94RczbdNix9/kQh38WiQkM90sUOi3if8eyHFgiBjBjhwXrA7W3ydiSQP9mw== "@tootallnate/once@2": version "2.0.0" resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf" integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A== +"@types/shimmer@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@types/shimmer/-/shimmer-1.0.2.tgz#93eb2c243c351f3f17d5c580c7467ae5d686b65f" + integrity sha512-dKkr1bTxbEsFlh2ARpKzcaAmsYixqt9UyCdoEZk8rHyE4iQYcDCyvSjDSf7JUWJHlJiTtbIoQjxKh6ViywqDAg== + "@types/vscode-webview@^1.57.0": version "1.57.0" resolved "https://registry.yarnpkg.com/@types/vscode-webview/-/vscode-webview-1.57.0.tgz#bad5194d45ae8d03afc1c0f67f71ff5e7a243bbf" integrity sha512-x3Cb/SMa1IwRHfSvKaZDZOTh4cNoG505c3NjTqGlMC082m++x/ETUmtYniDsw6SSmYzZXO8KBNhYxR0+VqymqA== -"@vscode/extension-telemetry@0.7.5": - version "0.7.5" - resolved "https://registry.yarnpkg.com/@vscode/extension-telemetry/-/extension-telemetry-0.7.5.tgz#bf965731816e08c3f146f96d901ec67954fc913b" - integrity sha512-fJ5y3TcpqqkFYHneabYaoB4XAhDdVflVm+TDKshw9VOs77jkgNS4UA7LNXrWeO0eDne3Sh3JgURf+xzc1rk69w== +"@vscode/extension-telemetry@^0.8.4": + version "0.8.4" + resolved "https://registry.yarnpkg.com/@vscode/extension-telemetry/-/extension-telemetry-0.8.4.tgz#c078c6f55df1c9e0592de3b4ce0f685dd345bfe7" + integrity sha512-UqM9+KZDDK3MyoHTsg6XNM+XO6pweQxzCpqJz33BoBEYAGsbBviRYcVpJglgay2oReuDD2pOI1Nio3BKNDLhWA== dependencies: - "@microsoft/1ds-core-js" "^3.2.8" - "@microsoft/1ds-post-js" "^3.2.8" - "@microsoft/applicationinsights-web-basic" "^2.8.9" - applicationinsights "2.4.1" + "@microsoft/1ds-core-js" "^3.2.13" + "@microsoft/1ds-post-js" "^3.2.13" + "@microsoft/applicationinsights-web-basic" "^3.0.2" + applicationinsights "^2.7.1" + +acorn-import-assertions@^1.9.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz#507276249d684797c84e0734ef84860334cfb1ac" + integrity sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA== + +acorn@^8.8.2: + version "8.10.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5" + integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw== agent-base@6: version "6.0.2" @@ -187,22 +296,24 @@ agent-base@6: dependencies: debug "4" -applicationinsights@2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/applicationinsights/-/applicationinsights-2.4.1.tgz#4de4c4dd3c7c4a44445cfbf3d15808fc0dcc423d" - integrity sha512-0n0Ikd0gzSm460xm+M0UTWIwXrhrH/0bqfZatcJjYObWyefxfAxapGEyNnSGd1Tg90neHz+Yhf+Ff/zgvPiQYA== +applicationinsights@^2.7.1: + version "2.7.3" + resolved "https://registry.yarnpkg.com/applicationinsights/-/applicationinsights-2.7.3.tgz#8781454d29c0b14c9773f2e892b4cf5e7468ffa5" + integrity sha512-JY8+kTEkjbA+kAVNWDtpfW2lqsrDALfDXuxOs74KLPu2y13fy/9WB52V4LfYVTVcW1/jYOXjTxNS2gPZIDh1iw== dependencies: - "@azure/core-auth" "^1.4.0" - "@azure/core-rest-pipeline" "^1.10.0" + "@azure/core-auth" "^1.5.0" + "@azure/core-rest-pipeline" "1.10.1" + "@azure/core-util" "1.2.0" + "@azure/opentelemetry-instrumentation-azure-sdk" "^1.0.0-beta.5" "@microsoft/applicationinsights-web-snippet" "^1.0.1" - "@opentelemetry/api" "^1.0.4" - "@opentelemetry/core" "^1.0.1" - "@opentelemetry/sdk-trace-base" "^1.0.1" - "@opentelemetry/semantic-conventions" "^1.0.1" + "@opentelemetry/api" "^1.4.1" + "@opentelemetry/core" "^1.15.2" + "@opentelemetry/sdk-trace-base" "^1.15.2" + "@opentelemetry/semantic-conventions" "^1.15.2" cls-hooked "^4.2.2" continuation-local-storage "^3.2.1" - diagnostic-channel "1.1.0" - diagnostic-channel-publishers "1.0.5" + diagnostic-channel "1.1.1" + diagnostic-channel-publishers "1.0.7" async-hook-jl@^1.7.6: version "1.7.6" @@ -224,6 +335,11 @@ asynckit@^0.4.0: resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== +cjs-module-lexer@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz#6c370ab19f8a3394e318fe682686ec0ac684d107" + integrity sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ== + cls-hooked@^4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/cls-hooked/-/cls-hooked-4.2.2.tgz#ad2e9a4092680cdaffeb2d3551da0e225eae1908" @@ -248,7 +364,7 @@ continuation-local-storage@^3.2.1: async-listener "^0.6.0" emitter-listener "^1.1.1" -debug@4: +debug@4, debug@^4.1.1: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== @@ -260,17 +376,17 @@ delayed-stream@~1.0.0: resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== -diagnostic-channel-publishers@1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/diagnostic-channel-publishers/-/diagnostic-channel-publishers-1.0.5.tgz#df8c317086c50f5727fdfb5d2fce214d2e4130ae" - integrity sha512-dJwUS0915pkjjimPJVDnS/QQHsH0aOYhnZsLJdnZIMOrB+csj8RnZhWTuwnm8R5v3Z7OZs+ksv5luC14DGB7eg== +diagnostic-channel-publishers@1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/diagnostic-channel-publishers/-/diagnostic-channel-publishers-1.0.7.tgz#9b7f8d5ee1295481aee19c827d917e96fedf2c4a" + integrity sha512-SEECbY5AiVt6DfLkhkaHNeshg1CogdLLANA8xlG/TKvS+XUgvIKl7VspJGYiEdL5OUyzMVnr7o0AwB7f+/Mjtg== -diagnostic-channel@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/diagnostic-channel/-/diagnostic-channel-1.1.0.tgz#6985e9dfedfbc072d91dc4388477e4087147756e" - integrity sha512-fwujyMe1gj6rk6dYi9hMZm0c8Mz8NDMVl2LB4iaYh3+LIAThZC8RKFGXWG0IML2OxAit/ZFRgZhMkhQ3d/bobQ== +diagnostic-channel@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/diagnostic-channel/-/diagnostic-channel-1.1.1.tgz#44b60972de9ee055c16216535b0e9db3f6a0efd0" + integrity sha512-r2HV5qFkUICyoaKlBEpLKHjxMXATUf/l+h8UZPGBHGLy4DDiY2sOLcIctax4eRnTw5wH2jTMExLntGPJ8eOJxw== dependencies: - semver "^5.3.0" + semver "^7.5.3" emitter-listener@^1.0.1, emitter-listener@^1.1.1: version "1.1.2" @@ -288,6 +404,18 @@ form-data@^4.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + http-proxy-agent@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz#5129800203520d434f142bc78ff3c170800f2b43" @@ -305,6 +433,30 @@ https-proxy-agent@^5.0.0: agent-base "6" debug "4" +import-in-the-middle@1.4.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/import-in-the-middle/-/import-in-the-middle-1.4.2.tgz#2a266676e3495e72c04bbaa5ec14756ba168391b" + integrity sha512-9WOz1Yh/cvO/p69sxRmhyQwrIGGSp7EIdcb+fFNVi7CzQGQB8U1/1XrKVSbEd/GNOAeM0peJtmi7+qphe7NvAw== + dependencies: + acorn "^8.8.2" + acorn-import-assertions "^1.9.0" + cjs-module-lexer "^1.2.2" + module-details-from-path "^1.0.3" + +is-core-module@^2.13.0: + version "2.13.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.0.tgz#bb52aa6e2cbd49a30c2ba68c42bf3435ba6072db" + integrity sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ== + dependencies: + has "^1.0.3" + +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + mime-db@1.52.0: version "1.52.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" @@ -317,17 +469,52 @@ mime-types@^2.1.12: dependencies: mime-db "1.52.0" +module-details-from-path@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/module-details-from-path/-/module-details-from-path-1.0.3.tgz#114c949673e2a8a35e9d35788527aa37b679da2b" + integrity sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A== + ms@2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +require-in-the-middle@^7.1.1: + version "7.2.0" + resolved "https://registry.yarnpkg.com/require-in-the-middle/-/require-in-the-middle-7.2.0.tgz#b539de8f00955444dc8aed95e17c69b0a4f10fcf" + integrity sha512-3TLx5TGyAY6AOqLBoXmHkNql0HIf2RGbuMgCDT2WO/uGVAPJs6h7Kl+bN6TIZGd9bWhWPwnDnTHGtW8Iu77sdw== + dependencies: + debug "^4.1.1" + module-details-from-path "^1.0.3" + resolve "^1.22.1" + +resolve@^1.22.1: + version "1.22.4" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.4.tgz#1dc40df46554cdaf8948a486a10f6ba1e2026c34" + integrity sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg== + dependencies: + is-core-module "^2.13.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + semver@^5.3.0, semver@^5.4.1: version "5.7.2" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== -shimmer@^1.1.0, shimmer@^1.2.0: +semver@^7.5.1, semver@^7.5.3: + version "7.5.4" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" + integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== + dependencies: + lru-cache "^6.0.0" + +shimmer@^1.1.0, shimmer@^1.2.0, shimmer@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/shimmer/-/shimmer-1.2.1.tgz#610859f7de327b587efebf501fb43117f9aff337" integrity sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw== @@ -337,6 +524,11 @@ stack-chain@^1.3.7: resolved "https://registry.yarnpkg.com/stack-chain/-/stack-chain-1.3.7.tgz#d192c9ff4ea6a22c94c4dd459171e3f00cea1285" integrity sha512-D8cWtWVdIe/jBA7v5p5Hwl5yOSOrmZPWDPe2KxQ5UAGD+nxbxU0lKXA4h85Ta6+qgdKVL3vUxsbIZjc1kBG7ug== +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + tslib@^2.2.0: version "2.4.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.1.tgz#0d0bfbaac2880b91e22df0768e55be9753a5b17e" @@ -351,3 +543,8 @@ vscode-codicons@^0.0.14: version "0.0.14" resolved "https://registry.yarnpkg.com/vscode-codicons/-/vscode-codicons-0.0.14.tgz#e0d05418e2e195564ff6f6a2199d70415911c18f" integrity sha512-6CEH5KT9ct5WMw7n5dlX7rB8ya4CUI2FSq1Wk36XaW+c5RglFtAanUV0T+gvZVVFhl/WxfjTvFHq06Hz9c1SLA== + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== diff --git a/extensions/typescript-language-features/package.json b/extensions/typescript-language-features/package.json index d855af70e68..e3c9a7f870d 100644 --- a/extensions/typescript-language-features/package.json +++ b/extensions/typescript-language-features/package.json @@ -33,7 +33,7 @@ "Programming Languages" ], "dependencies": { - "@vscode/extension-telemetry": "0.7.5", + "@vscode/extension-telemetry": "^0.8.4", "jsonc-parser": "^3.2.0", "semver": "7.5.2", "vscode-tas-client": "^0.1.63", diff --git a/extensions/typescript-language-features/yarn.lock b/extensions/typescript-language-features/yarn.lock index 1b011de0449..eedf2d9c580 100644 --- a/extensions/typescript-language-features/yarn.lock +++ b/extensions/typescript-language-features/yarn.lock @@ -17,7 +17,16 @@ "@azure/abort-controller" "^1.0.0" tslib "^2.2.0" -"@azure/core-rest-pipeline@^1.10.0": +"@azure/core-auth@^1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@azure/core-auth/-/core-auth-1.5.0.tgz#a41848c5c31cb3b7c84c409885267d55a2c92e44" + integrity sha512-udzoBuYG1VBoHVohDTrvKjyzel34zt77Bhp7dQntVGGD0ehVq48owENbBG8fIgkHRNUBQH5k1r0hpoMu5L8+kw== + dependencies: + "@azure/abort-controller" "^1.0.0" + "@azure/core-util" "^1.1.0" + tslib "^2.2.0" + +"@azure/core-rest-pipeline@1.10.1": version "1.10.1" resolved "https://registry.yarnpkg.com/@azure/core-rest-pipeline/-/core-rest-pipeline-1.10.1.tgz#348290847ca31b9eecf9cf5de7519aaccdd30968" integrity sha512-Kji9k6TOFRDB5ZMTw8qUf2IJ+CeJtsuMdAHox9eqpTf1cefiNMpzrfnF6sINEBZJsaVaWgQ0o48B6kcUH68niA== @@ -33,13 +42,21 @@ tslib "^2.2.0" uuid "^8.3.0" -"@azure/core-tracing@^1.0.1": +"@azure/core-tracing@^1.0.0", "@azure/core-tracing@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@azure/core-tracing/-/core-tracing-1.0.1.tgz#352a38cbea438c4a83c86b314f48017d70ba9503" integrity sha512-I5CGMoLtX+pI17ZdiFJZgxMJApsK6jjfm85hpgp3oazCdq5Wxgh4wMr7ge/TTWW1B5WBuvIOI1fMU/FrOAMKrw== dependencies: tslib "^2.2.0" +"@azure/core-util@1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@azure/core-util/-/core-util-1.2.0.tgz#3499deba1fc36dda6f1912b791809b6f15d4a392" + integrity sha512-ffGIw+Qs8bNKNLxz5UPkz4/VBM/EZY07mPve1ZYFqYUdPwFqRj0RPk0U7LZMOfT7GCck9YjuT1Rfp1PApNl1ng== + dependencies: + "@azure/abort-controller" "^1.0.0" + tslib "^2.2.0" + "@azure/core-util@^1.0.0": version "1.1.1" resolved "https://registry.yarnpkg.com/@azure/core-util/-/core-util-1.1.1.tgz#8f87b3dd468795df0f0849d9f096c3e7b29452c1" @@ -48,6 +65,14 @@ "@azure/abort-controller" "^1.0.0" tslib "^2.2.0" +"@azure/core-util@^1.1.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@azure/core-util/-/core-util-1.4.0.tgz#c120a56b3e48a9e4d20619a0b00268ae9de891c7" + integrity sha512-eGAyJpm3skVQoLiRqm/xPa+SXi/NPDdSHMxbRAz2lSprd+Zs+qrpQGQQ2VQ3Nttu+nSZR4XoYQC71LbEI7jsig== + dependencies: + "@azure/abort-controller" "^1.0.0" + tslib "^2.2.0" + "@azure/logger@^1.0.0": version "1.0.3" resolved "https://registry.yarnpkg.com/@azure/logger/-/logger-1.0.3.tgz#6e36704aa51be7d4a1bae24731ea580836293c96" @@ -55,66 +80,100 @@ dependencies: tslib "^2.2.0" -"@microsoft/1ds-core-js@3.2.8", "@microsoft/1ds-core-js@^3.2.8": - version "3.2.8" - resolved "https://registry.yarnpkg.com/@microsoft/1ds-core-js/-/1ds-core-js-3.2.8.tgz#1b6b7d9bb858238c818ccf4e4b58ece7aeae5760" - integrity sha512-9o9SUAamJiTXIYwpkQDuueYt83uZfXp8zp8YFix1IwVPwC9RmE36T2CX9gXOeq1nDckOuOduYpA8qHvdh5BGfQ== +"@azure/opentelemetry-instrumentation-azure-sdk@^1.0.0-beta.5": + version "1.0.0-beta.5" + resolved "https://registry.yarnpkg.com/@azure/opentelemetry-instrumentation-azure-sdk/-/opentelemetry-instrumentation-azure-sdk-1.0.0-beta.5.tgz#78809e6c005d08450701e5d37f087f6fce2f86eb" + integrity sha512-fsUarKQDvjhmBO4nIfaZkfNSApm1hZBzcvpNbSrXdcUBxu7lRvKsV5DnwszX7cnhLyVOW9yl1uigtRQ1yDANjA== dependencies: - "@microsoft/applicationinsights-core-js" "2.8.9" + "@azure/core-tracing" "^1.0.0" + "@azure/logger" "^1.0.0" + "@opentelemetry/api" "^1.4.1" + "@opentelemetry/core" "^1.15.2" + "@opentelemetry/instrumentation" "^0.41.2" + tslib "^2.2.0" + +"@microsoft/1ds-core-js@3.2.13", "@microsoft/1ds-core-js@^3.2.13": + version "3.2.13" + resolved "https://registry.yarnpkg.com/@microsoft/1ds-core-js/-/1ds-core-js-3.2.13.tgz#0c105ed75091bae3f1555c0334704fa9911c58fb" + integrity sha512-CluYTRWcEk0ObG5EWFNWhs87e2qchJUn0p2D21ZUa3PWojPZfPSBs4//WIE0MYV8Qg1Hdif2ZTwlM7TbYUjfAg== + dependencies: + "@microsoft/applicationinsights-core-js" "2.8.15" "@microsoft/applicationinsights-shims" "^2.0.2" "@microsoft/dynamicproto-js" "^1.1.7" -"@microsoft/1ds-post-js@^3.2.8": - version "3.2.8" - resolved "https://registry.yarnpkg.com/@microsoft/1ds-post-js/-/1ds-post-js-3.2.8.tgz#46793842cca161bf7a2a5b6053c349f429e55110" - integrity sha512-SjlRoNcXcXBH6WQD/5SkkaCHIVqldH3gDu+bI7YagrOVJ5APxwT1Duw9gm3L1FjFa9S2i81fvJ3EVSKpp9wULA== +"@microsoft/1ds-post-js@^3.2.13": + version "3.2.13" + resolved "https://registry.yarnpkg.com/@microsoft/1ds-post-js/-/1ds-post-js-3.2.13.tgz#560aacac8a92fdbb79e8c2ebcb293d56e19f51aa" + integrity sha512-HgS574fdD19Bo2vPguyznL4eDw7Pcm1cVNpvbvBLWiW3x4e1FCQ3VMXChWnAxCae8Hb0XqlA2sz332ZobBavTA== dependencies: - "@microsoft/1ds-core-js" "3.2.8" + "@microsoft/1ds-core-js" "3.2.13" "@microsoft/applicationinsights-shims" "^2.0.2" "@microsoft/dynamicproto-js" "^1.1.7" -"@microsoft/applicationinsights-channel-js@2.8.9": - version "2.8.9" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-channel-js/-/applicationinsights-channel-js-2.8.9.tgz#840656f3c716de8b3eb0a98c122aa1b92bb8ebfb" - integrity sha512-fMBsAEB7pWtPn43y72q9Xy5E5y55r6gMuDQqRRccccVoQDPXyS57VCj5IdATblctru0C6A8XpL2vRyNmEsu0Vg== +"@microsoft/applicationinsights-channel-js@3.0.2": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-channel-js/-/applicationinsights-channel-js-3.0.2.tgz#be49fbf74831c7b8c97950027c5052ea99d2a8a5" + integrity sha512-jDBNKbCHsJgmpv0CKNhJ/uN9ZphvfGdb93Svk+R4LjO8L3apNNMbDDPxBvXXi0uigRmA1TBcmyBG4IRKjabGhw== dependencies: - "@microsoft/applicationinsights-common" "2.8.9" - "@microsoft/applicationinsights-core-js" "2.8.9" - "@microsoft/applicationinsights-shims" "2.0.2" - "@microsoft/dynamicproto-js" "^1.1.7" + "@microsoft/applicationinsights-common" "3.0.2" + "@microsoft/applicationinsights-core-js" "3.0.2" + "@microsoft/applicationinsights-shims" "3.0.1" + "@microsoft/dynamicproto-js" "^2.0.2" + "@nevware21/ts-async" ">= 0.2.4 < 2.x" + "@nevware21/ts-utils" ">= 0.9.5 < 2.x" -"@microsoft/applicationinsights-common@2.8.9": - version "2.8.9" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-common/-/applicationinsights-common-2.8.9.tgz#a75e4a3143a7fd797687830c0ddd2069fd900827" - integrity sha512-mObn1moElyxZaGIRF/IU3cOaeKMgxghXnYEoHNUCA2e+rNwBIgxjyKkblFIpmGuHf4X7Oz3o3yBWpaC6AoMpig== +"@microsoft/applicationinsights-common@3.0.2": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-common/-/applicationinsights-common-3.0.2.tgz#37670bb07f4858ed41ff9759119e0759007d6e05" + integrity sha512-y+WXWop+OVim954Cu1uyYMnNx6PWO8okHpZIQi/1YSqtqaYdtJVPv4P0AVzwJdohxzVfgzKvqj9nec/VWqE2Zg== dependencies: - "@microsoft/applicationinsights-core-js" "2.8.9" - "@microsoft/applicationinsights-shims" "2.0.2" - "@microsoft/dynamicproto-js" "^1.1.7" + "@microsoft/applicationinsights-core-js" "3.0.2" + "@microsoft/applicationinsights-shims" "3.0.1" + "@microsoft/dynamicproto-js" "^2.0.2" + "@nevware21/ts-utils" ">= 0.9.5 < 2.x" -"@microsoft/applicationinsights-core-js@2.8.9": - version "2.8.9" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-2.8.9.tgz#0e5d207acfae6986a6fc97249eeb6117e523bf1b" - integrity sha512-HRuIuZ6aOWezcg/G5VyFDDWGL8hDNe/ljPP01J7ImH2kRPEgbtcfPSUMjkamGMefgdq81GZsSoC/NNGTP4pp2w== +"@microsoft/applicationinsights-core-js@2.8.15": + version "2.8.15" + resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-2.8.15.tgz#8fa466474260e01967fe649f14dd9e5ff91dcdc8" + integrity sha512-yYAs9MyjGr2YijQdUSN9mVgT1ijI1FPMgcffpaPmYbHAVbQmF7bXudrBWHxmLzJlwl5rfep+Zgjli2e67lwUqQ== dependencies: "@microsoft/applicationinsights-shims" "2.0.2" - "@microsoft/dynamicproto-js" "^1.1.7" + "@microsoft/dynamicproto-js" "^1.1.9" + +"@microsoft/applicationinsights-core-js@3.0.2": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-3.0.2.tgz#108e20df8c162bec92b1f66f9de2530a25d9f51a" + integrity sha512-WQhVhzlRlLDrQzn3OShCW/pL3BW5WC57t0oywSknX3q7lMzI3jDg7Ihh0iuIcNTzGCTbDkuqr4d6IjEDWIMtJQ== + dependencies: + "@microsoft/applicationinsights-shims" "3.0.1" + "@microsoft/dynamicproto-js" "^2.0.2" + "@nevware21/ts-async" ">= 0.2.4 < 2.x" + "@nevware21/ts-utils" ">= 0.9.5 < 2.x" "@microsoft/applicationinsights-shims@2.0.2", "@microsoft/applicationinsights-shims@^2.0.2": version "2.0.2" resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-shims/-/applicationinsights-shims-2.0.2.tgz#92b36a09375e2d9cb2b4203383b05772be837085" integrity sha512-PoHEgsnmcqruLNHZ/amACqdJ6YYQpED0KSRe6J7gIJTtpZC1FfFU9b1fmDKDKtFoUSrPzEh1qzO3kmRZP0betg== -"@microsoft/applicationinsights-web-basic@^2.8.9": - version "2.8.9" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-web-basic/-/applicationinsights-web-basic-2.8.9.tgz#eed2f3d1e19069962ed2155915c1656e6936e1d5" - integrity sha512-CH0J8JFOy7MjK8JO4pXXU+EML+Ilix+94PMZTX5EJlBU1in+mrik74/8qSg3UC4ekPi12KwrXaHCQSVC3WseXQ== +"@microsoft/applicationinsights-shims@3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-shims/-/applicationinsights-shims-3.0.1.tgz#3865b73ace8405b9c4618cc5c571f2fe3876f06f" + integrity sha512-DKwboF47H1nb33rSUfjqI6ryX29v+2QWcTrRvcQDA32AZr5Ilkr7whOOSsD1aBzwqX0RJEIP1Z81jfE3NBm/Lg== dependencies: - "@microsoft/applicationinsights-channel-js" "2.8.9" - "@microsoft/applicationinsights-common" "2.8.9" - "@microsoft/applicationinsights-core-js" "2.8.9" - "@microsoft/applicationinsights-shims" "2.0.2" - "@microsoft/dynamicproto-js" "^1.1.7" + "@nevware21/ts-utils" ">= 0.9.4 < 2.x" + +"@microsoft/applicationinsights-web-basic@^3.0.2": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-web-basic/-/applicationinsights-web-basic-3.0.2.tgz#f777a4d24b79dde3ae396d3b819e1fce06b7240a" + integrity sha512-6Lq0DE/pZp9RvSV+weGbcxN1NDmfczj6gNPhvZKV2YSQ3RK0LZE3+wjTWLXfuStq8a+nCBdsRpWk8tOKgsoxcg== + dependencies: + "@microsoft/applicationinsights-channel-js" "3.0.2" + "@microsoft/applicationinsights-common" "3.0.2" + "@microsoft/applicationinsights-core-js" "3.0.2" + "@microsoft/applicationinsights-shims" "3.0.1" + "@microsoft/dynamicproto-js" "^2.0.2" + "@nevware21/ts-async" ">= 0.2.4 < 2.x" + "@nevware21/ts-utils" ">= 0.9.5 < 2.x" "@microsoft/applicationinsights-web-snippet@^1.0.1": version "1.0.1" @@ -126,39 +185,74 @@ resolved "https://registry.yarnpkg.com/@microsoft/dynamicproto-js/-/dynamicproto-js-1.1.7.tgz#ede48dd3f85af14ee369c805e5ed5b84222b9fe2" integrity sha512-SK3D3aVt+5vOOccKPnGaJWB5gQ8FuKfjboUJHedMP7gu54HqSCXX5iFXhktGD8nfJb0Go30eDvs/UDoTnR2kOA== -"@opentelemetry/api@^1.0.4": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.2.0.tgz#89ef99401cde6208cff98760b67663726ef26686" - integrity sha512-0nBr+VZNKm9tvNDZFstI3Pq1fCTEDK5OZTnVKNvBNAKgd0yIvmwsP4m61rEv7ZP+tOUjWJhROpxK5MsnlF911g== +"@microsoft/dynamicproto-js@^1.1.9": + version "1.1.9" + resolved "https://registry.yarnpkg.com/@microsoft/dynamicproto-js/-/dynamicproto-js-1.1.9.tgz#7437db7aa061162ee94e4131b69a62b8dad5dea6" + integrity sha512-n1VPsljTSkthsAFYdiWfC+DKzK2WwcRp83Y1YAqdX552BstvsDjft9YXppjUzp11BPsapDoO1LDgrDB0XVsfNQ== -"@opentelemetry/core@1.7.0", "@opentelemetry/core@^1.0.1": - version "1.7.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-1.7.0.tgz#83bdd1b7a4ceafcdffd6590420657caec5f7b34c" - integrity sha512-AVqAi5uc8DrKJBimCTFUT4iFI+5eXpo4sYmGbQ0CypG0piOTHE2g9c5aSoTGYXu3CzOmJZf7pT6Xh+nwm5d6yQ== +"@microsoft/dynamicproto-js@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@microsoft/dynamicproto-js/-/dynamicproto-js-2.0.2.tgz#e57fbec2e7067d48b7e8e1e1c1d354028ef718a6" + integrity sha512-MB8trWaFREpmb037k/d0bB7T2BP7Ai24w1e1tbz3ASLB0/lwphsq3Nq8S9I5AsI5vs4zAQT+SB5nC5/dLYTiOg== dependencies: - "@opentelemetry/semantic-conventions" "1.7.0" + "@nevware21/ts-utils" ">= 0.9.4 < 2.x" -"@opentelemetry/resources@1.7.0": - version "1.7.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/resources/-/resources-1.7.0.tgz#90ccd3a6a86b4dfba4e833e73944bd64958d78c5" - integrity sha512-u1M0yZotkjyKx8dj+46Sg5thwtOTBmtRieNXqdCRiWUp6SfFiIP0bI+1XK3LhuXqXkBXA1awJZaTqKduNMStRg== +"@nevware21/ts-async@>= 0.2.4 < 2.x": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@nevware21/ts-async/-/ts-async-0.3.0.tgz#a8b97ba01065fc930de9a3f4dd4a05e862becc6c" + integrity sha512-ZUcgUH12LN/F6nzN0cYd0F/rJaMLmXr0EHVTyYfaYmK55bdwE4338uue4UiVoRqHVqNW4KDUrJc49iGogHKeWA== dependencies: - "@opentelemetry/core" "1.7.0" - "@opentelemetry/semantic-conventions" "1.7.0" + "@nevware21/ts-utils" ">= 0.10.0 < 2.x" -"@opentelemetry/sdk-trace-base@^1.0.1": - version "1.7.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.7.0.tgz#b498424e0c6340a9d80de63fd408c5c2130a60a5" - integrity sha512-Iz84C+FVOskmauh9FNnj4+VrA+hG5o+tkMzXuoesvSfunVSioXib0syVFeNXwOm4+M5GdWCuW632LVjqEXStIg== +"@nevware21/ts-utils@>= 0.10.0 < 2.x", "@nevware21/ts-utils@>= 0.9.4 < 2.x", "@nevware21/ts-utils@>= 0.9.5 < 2.x": + version "0.10.1" + resolved "https://registry.yarnpkg.com/@nevware21/ts-utils/-/ts-utils-0.10.1.tgz#aa65abc71eba06749a396598f22263d26f796ac7" + integrity sha512-pMny25NnF2/MJwdqC3Iyjm2pGIXNxni4AROpcqDeWa+td9JMUY4bUS9uU9XW+BoBRqTLUL+WURF9SOd/6OQzRg== + +"@opentelemetry/api@^1.4.1": + version "1.4.1" + resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.4.1.tgz#ff22eb2e5d476fbc2450a196e40dd243cc20c28f" + integrity sha512-O2yRJce1GOc6PAy3QxFM4NzFiWzvScDC1/5ihYBL6BUEVdq0XMWN01sppE+H6bBXbaFYipjwFLEWLg5PaSOThA== + +"@opentelemetry/core@1.15.2", "@opentelemetry/core@^1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-1.15.2.tgz#5b170bf223a2333884bbc2d29d95812cdbda7c9f" + integrity sha512-+gBv15ta96WqkHZaPpcDHiaz0utiiHZVfm2YOYSqFGrUaJpPkMoSuLBB58YFQGi6Rsb9EHos84X6X5+9JspmLw== dependencies: - "@opentelemetry/core" "1.7.0" - "@opentelemetry/resources" "1.7.0" - "@opentelemetry/semantic-conventions" "1.7.0" + "@opentelemetry/semantic-conventions" "1.15.2" -"@opentelemetry/semantic-conventions@1.7.0", "@opentelemetry/semantic-conventions@^1.0.1": - version "1.7.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.7.0.tgz#af80a1ef7cf110ea3a68242acd95648991bcd763" - integrity sha512-FGBx/Qd09lMaqQcogCHyYrFEpTx4cAjeS+48lMIR12z7LdH+zofGDVQSubN59nL6IpubfKqTeIDu9rNO28iHVA== +"@opentelemetry/instrumentation@^0.41.2": + version "0.41.2" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation/-/instrumentation-0.41.2.tgz#cae11fa64485dcf03dae331f35b315b64bc6189f" + integrity sha512-rxU72E0pKNH6ae2w5+xgVYZLzc5mlxAbGzF4shxMVK8YC2QQsfN38B2GPbj0jvrKWWNUElfclQ+YTykkNg/grw== + dependencies: + "@types/shimmer" "^1.0.2" + import-in-the-middle "1.4.2" + require-in-the-middle "^7.1.1" + semver "^7.5.1" + shimmer "^1.2.1" + +"@opentelemetry/resources@1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@opentelemetry/resources/-/resources-1.15.2.tgz#0c9e26cb65652a1402834a3c030cce6028d6dd9d" + integrity sha512-xmMRLenT9CXmm5HMbzpZ1hWhaUowQf8UB4jMjFlAxx1QzQcsD3KFNAVX/CAWzFPtllTyTplrA4JrQ7sCH3qmYw== + dependencies: + "@opentelemetry/core" "1.15.2" + "@opentelemetry/semantic-conventions" "1.15.2" + +"@opentelemetry/sdk-trace-base@^1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.15.2.tgz#4821f94033c55a6c8bbd35ae387b715b6108517a" + integrity sha512-BEaxGZbWtvnSPchV98qqqqa96AOcb41pjgvhfzDij10tkBhIu9m0Jd6tZ1tJB5ZHfHbTffqYVYE0AOGobec/EQ== + dependencies: + "@opentelemetry/core" "1.15.2" + "@opentelemetry/resources" "1.15.2" + "@opentelemetry/semantic-conventions" "1.15.2" + +"@opentelemetry/semantic-conventions@1.15.2", "@opentelemetry/semantic-conventions@^1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.15.2.tgz#3bafb5de3e20e841dff6cb3c66f4d6e9694c4241" + integrity sha512-CjbOKwk2s+3xPIMcd5UNYQzsf+v94RczbdNix9/kQh38WiQkM90sUOi3if8eyHFgiBjBjhwXrA7W3ydiSQP9mw== "@tootallnate/once@2": version "2.0.0" @@ -175,15 +269,20 @@ resolved "https://registry.yarnpkg.com/@types/semver/-/semver-5.5.0.tgz#146c2a29ee7d3bae4bf2fcb274636e264c813c45" integrity sha512-41qEJgBH/TWgo5NFSvBCJ1qkoi3Q6ONSF2avrHq1LVEZfYpdHmj0y9SuTK+u9ZhG1sYQKBL1AWXKyLWP4RaUoQ== -"@vscode/extension-telemetry@0.7.5": - version "0.7.5" - resolved "https://registry.yarnpkg.com/@vscode/extension-telemetry/-/extension-telemetry-0.7.5.tgz#bf965731816e08c3f146f96d901ec67954fc913b" - integrity sha512-fJ5y3TcpqqkFYHneabYaoB4XAhDdVflVm+TDKshw9VOs77jkgNS4UA7LNXrWeO0eDne3Sh3JgURf+xzc1rk69w== +"@types/shimmer@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@types/shimmer/-/shimmer-1.0.2.tgz#93eb2c243c351f3f17d5c580c7467ae5d686b65f" + integrity sha512-dKkr1bTxbEsFlh2ARpKzcaAmsYixqt9UyCdoEZk8rHyE4iQYcDCyvSjDSf7JUWJHlJiTtbIoQjxKh6ViywqDAg== + +"@vscode/extension-telemetry@^0.8.4": + version "0.8.4" + resolved "https://registry.yarnpkg.com/@vscode/extension-telemetry/-/extension-telemetry-0.8.4.tgz#c078c6f55df1c9e0592de3b4ce0f685dd345bfe7" + integrity sha512-UqM9+KZDDK3MyoHTsg6XNM+XO6pweQxzCpqJz33BoBEYAGsbBviRYcVpJglgay2oReuDD2pOI1Nio3BKNDLhWA== dependencies: - "@microsoft/1ds-core-js" "^3.2.8" - "@microsoft/1ds-post-js" "^3.2.8" - "@microsoft/applicationinsights-web-basic" "^2.8.9" - applicationinsights "2.4.1" + "@microsoft/1ds-core-js" "^3.2.13" + "@microsoft/1ds-post-js" "^3.2.13" + "@microsoft/applicationinsights-web-basic" "^3.0.2" + applicationinsights "^2.7.1" "@vscode/sync-api-client@^0.7.2": version "0.7.2" @@ -206,6 +305,16 @@ "@vscode/sync-api-common" "0.7.2" vscode-uri "3.0.3" +acorn-import-assertions@^1.9.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz#507276249d684797c84e0734ef84860334cfb1ac" + integrity sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA== + +acorn@^8.8.2: + version "8.10.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5" + integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw== + agent-base@6: version "6.0.2" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" @@ -213,22 +322,24 @@ agent-base@6: dependencies: debug "4" -applicationinsights@2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/applicationinsights/-/applicationinsights-2.4.1.tgz#4de4c4dd3c7c4a44445cfbf3d15808fc0dcc423d" - integrity sha512-0n0Ikd0gzSm460xm+M0UTWIwXrhrH/0bqfZatcJjYObWyefxfAxapGEyNnSGd1Tg90neHz+Yhf+Ff/zgvPiQYA== +applicationinsights@^2.7.1: + version "2.7.3" + resolved "https://registry.yarnpkg.com/applicationinsights/-/applicationinsights-2.7.3.tgz#8781454d29c0b14c9773f2e892b4cf5e7468ffa5" + integrity sha512-JY8+kTEkjbA+kAVNWDtpfW2lqsrDALfDXuxOs74KLPu2y13fy/9WB52V4LfYVTVcW1/jYOXjTxNS2gPZIDh1iw== dependencies: - "@azure/core-auth" "^1.4.0" - "@azure/core-rest-pipeline" "^1.10.0" + "@azure/core-auth" "^1.5.0" + "@azure/core-rest-pipeline" "1.10.1" + "@azure/core-util" "1.2.0" + "@azure/opentelemetry-instrumentation-azure-sdk" "^1.0.0-beta.5" "@microsoft/applicationinsights-web-snippet" "^1.0.1" - "@opentelemetry/api" "^1.0.4" - "@opentelemetry/core" "^1.0.1" - "@opentelemetry/sdk-trace-base" "^1.0.1" - "@opentelemetry/semantic-conventions" "^1.0.1" + "@opentelemetry/api" "^1.4.1" + "@opentelemetry/core" "^1.15.2" + "@opentelemetry/sdk-trace-base" "^1.15.2" + "@opentelemetry/semantic-conventions" "^1.15.2" cls-hooked "^4.2.2" continuation-local-storage "^3.2.1" - diagnostic-channel "1.1.0" - diagnostic-channel-publishers "1.0.5" + diagnostic-channel "1.1.1" + diagnostic-channel-publishers "1.0.7" async-hook-jl@^1.7.6: version "1.7.6" @@ -257,6 +368,11 @@ axios@^0.26.1: dependencies: follow-redirects "^1.14.8" +cjs-module-lexer@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz#6c370ab19f8a3394e318fe682686ec0ac684d107" + integrity sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ== + cls-hooked@^4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/cls-hooked/-/cls-hooked-4.2.2.tgz#ad2e9a4092680cdaffeb2d3551da0e225eae1908" @@ -281,7 +397,7 @@ continuation-local-storage@^3.2.1: async-listener "^0.6.0" emitter-listener "^1.1.1" -debug@4: +debug@4, debug@^4.1.1: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== @@ -293,17 +409,17 @@ delayed-stream@~1.0.0: resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== -diagnostic-channel-publishers@1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/diagnostic-channel-publishers/-/diagnostic-channel-publishers-1.0.5.tgz#df8c317086c50f5727fdfb5d2fce214d2e4130ae" - integrity sha512-dJwUS0915pkjjimPJVDnS/QQHsH0aOYhnZsLJdnZIMOrB+csj8RnZhWTuwnm8R5v3Z7OZs+ksv5luC14DGB7eg== +diagnostic-channel-publishers@1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/diagnostic-channel-publishers/-/diagnostic-channel-publishers-1.0.7.tgz#9b7f8d5ee1295481aee19c827d917e96fedf2c4a" + integrity sha512-SEECbY5AiVt6DfLkhkaHNeshg1CogdLLANA8xlG/TKvS+XUgvIKl7VspJGYiEdL5OUyzMVnr7o0AwB7f+/Mjtg== -diagnostic-channel@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/diagnostic-channel/-/diagnostic-channel-1.1.0.tgz#6985e9dfedfbc072d91dc4388477e4087147756e" - integrity sha512-fwujyMe1gj6rk6dYi9hMZm0c8Mz8NDMVl2LB4iaYh3+LIAThZC8RKFGXWG0IML2OxAit/ZFRgZhMkhQ3d/bobQ== +diagnostic-channel@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/diagnostic-channel/-/diagnostic-channel-1.1.1.tgz#44b60972de9ee055c16216535b0e9db3f6a0efd0" + integrity sha512-r2HV5qFkUICyoaKlBEpLKHjxMXATUf/l+h8UZPGBHGLy4DDiY2sOLcIctax4eRnTw5wH2jTMExLntGPJ8eOJxw== dependencies: - semver "^5.3.0" + semver "^7.5.3" emitter-listener@^1.0.1, emitter-listener@^1.1.1: version "1.1.2" @@ -326,6 +442,18 @@ form-data@^4.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + http-proxy-agent@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz#5129800203520d434f142bc78ff3c170800f2b43" @@ -343,6 +471,23 @@ https-proxy-agent@^5.0.0: agent-base "6" debug "4" +import-in-the-middle@1.4.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/import-in-the-middle/-/import-in-the-middle-1.4.2.tgz#2a266676e3495e72c04bbaa5ec14756ba168391b" + integrity sha512-9WOz1Yh/cvO/p69sxRmhyQwrIGGSp7EIdcb+fFNVi7CzQGQB8U1/1XrKVSbEd/GNOAeM0peJtmi7+qphe7NvAw== + dependencies: + acorn "^8.8.2" + acorn-import-assertions "^1.9.0" + cjs-module-lexer "^1.2.2" + module-details-from-path "^1.0.3" + +is-core-module@^2.13.0: + version "2.13.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.0.tgz#bb52aa6e2cbd49a30c2ba68c42bf3435ba6072db" + integrity sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ== + dependencies: + has "^1.0.3" + jsonc-parser@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.2.0.tgz#31ff3f4c2b9793f89c67212627c51c6394f88e76" @@ -367,11 +512,39 @@ mime-types@^2.1.12: dependencies: mime-db "1.52.0" +module-details-from-path@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/module-details-from-path/-/module-details-from-path-1.0.3.tgz#114c949673e2a8a35e9d35788527aa37b679da2b" + integrity sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A== + ms@2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +require-in-the-middle@^7.1.1: + version "7.2.0" + resolved "https://registry.yarnpkg.com/require-in-the-middle/-/require-in-the-middle-7.2.0.tgz#b539de8f00955444dc8aed95e17c69b0a4f10fcf" + integrity sha512-3TLx5TGyAY6AOqLBoXmHkNql0HIf2RGbuMgCDT2WO/uGVAPJs6h7Kl+bN6TIZGd9bWhWPwnDnTHGtW8Iu77sdw== + dependencies: + debug "^4.1.1" + module-details-from-path "^1.0.3" + resolve "^1.22.1" + +resolve@^1.22.1: + version "1.22.4" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.4.tgz#1dc40df46554cdaf8948a486a10f6ba1e2026c34" + integrity sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg== + dependencies: + is-core-module "^2.13.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + semver@7.5.2: version "7.5.2" resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.2.tgz#5b851e66d1be07c1cdaf37dfc856f543325a2beb" @@ -384,7 +557,14 @@ semver@^5.3.0, semver@^5.4.1: resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== -shimmer@^1.1.0, shimmer@^1.2.0: +semver@^7.5.1, semver@^7.5.3: + version "7.5.4" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" + integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== + dependencies: + lru-cache "^6.0.0" + +shimmer@^1.1.0, shimmer@^1.2.0, shimmer@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/shimmer/-/shimmer-1.2.1.tgz#610859f7de327b587efebf501fb43117f9aff337" integrity sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw== @@ -394,6 +574,11 @@ stack-chain@^1.3.7: resolved "https://registry.yarnpkg.com/stack-chain/-/stack-chain-1.3.7.tgz#d192c9ff4ea6a22c94c4dd459171e3f00cea1285" integrity sha512-D8cWtWVdIe/jBA7v5p5Hwl5yOSOrmZPWDPe2KxQ5UAGD+nxbxU0lKXA4h85Ta6+qgdKVL3vUxsbIZjc1kBG7ug== +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + tas-client@0.1.58: version "0.1.58" resolved "https://registry.yarnpkg.com/tas-client/-/tas-client-0.1.58.tgz#67d66bf0e27df5276ebc751105e6ad47791c36d8" From ee8edc4dc9e6cae4f879bd6ad9e05a9ab40e07ee Mon Sep 17 00:00:00 2001 From: Henning Dieterichs Date: Thu, 24 Aug 2023 22:32:45 +0200 Subject: [PATCH 203/221] Better moved code detection. --- src/vs/editor/common/diff/advancedLinesDiffComputer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/editor/common/diff/advancedLinesDiffComputer.ts b/src/vs/editor/common/diff/advancedLinesDiffComputer.ts index 61fd21d9c29..a7d9605d78c 100644 --- a/src/vs/editor/common/diff/advancedLinesDiffComputer.ts +++ b/src/vs/editor/common/diff/advancedLinesDiffComputer.ts @@ -311,7 +311,7 @@ export class AdvancedLinesDiffComputer implements ILinesDiffComputer { const modifiedDist = current.modified.startLineNumber - last.modified.endLineNumberExclusive; const currentMoveAfterLast = originalDist >= 0 && modifiedDist >= 0; - if (currentMoveAfterLast && originalDist <= 1 && modifiedDist <= 1) { + if (currentMoveAfterLast && originalDist + modifiedDist <= 2) { joinedMoves[joinedMoves.length - 1] = last.join(current); continue; } From 9e2cd079528bea00be8aabb16df1323683bb382d Mon Sep 17 00:00:00 2001 From: Henning Dieterichs Date: Thu, 24 Aug 2023 22:38:58 +0200 Subject: [PATCH 204/221] Use text instead of icon for moved code compare button --- .../browser/widget/diffEditorWidget2/movedBlocksLines.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vs/editor/browser/widget/diffEditorWidget2/movedBlocksLines.ts b/src/vs/editor/browser/widget/diffEditorWidget2/movedBlocksLines.ts index 6a5316decba..f52c55e389f 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget2/movedBlocksLines.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget2/movedBlocksLines.ts @@ -325,6 +325,7 @@ class MovedBlockOverlayWidget extends ViewZoneOverlayWidget { const isActive = this._diffModel.movedTextToCompare.read(reader) === _move; actionCompare.checked = isActive; })); - actionBar.push(actionCompare, { icon: true, label: false }); + + actionBar.push(actionCompare, { icon: false, label: true }); } } From 506e14d8db23cad93f15781ec2405780cab4d35a Mon Sep 17 00:00:00 2001 From: Henning Dieterichs Date: Thu, 24 Aug 2023 22:55:21 +0200 Subject: [PATCH 205/221] Fixes #191255 --- .../editor/browser/widget/diffEditorWidget2/movedBlocksLines.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/editor/browser/widget/diffEditorWidget2/movedBlocksLines.ts b/src/vs/editor/browser/widget/diffEditorWidget2/movedBlocksLines.ts index f52c55e389f..c4144924bce 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget2/movedBlocksLines.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget2/movedBlocksLines.ts @@ -145,7 +145,7 @@ export class MovedBlocksLinesPart extends Disposable { lines.sort(tieBreakComparators( compareBy(l => l.fromWithoutScroll > l.toWithoutScroll, booleanComparator), - compareBy(l => -l.fromWithoutScroll, numberComparator) + compareBy(l => l.fromWithoutScroll > l.toWithoutScroll ? l.fromWithoutScroll : -l.toWithoutScroll, numberComparator) )); const layout = LinesLayout.compute(lines.map(l => l.range)); From 9cd4c084dfd2cc9ef3c41d615898646b6c3f2896 Mon Sep 17 00:00:00 2001 From: meganrogge Date: Thu, 24 Aug 2023 14:43:06 -0700 Subject: [PATCH 206/221] reset context keys --- .../contrib/accessibility/browser/accessibleView.ts | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts b/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts index 506af0bfe15..02c1f17b6f6 100644 --- a/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts +++ b/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts @@ -170,6 +170,16 @@ class AccessibleView extends Disposable { this._updateToolbar(this._currentProvider.actions, this._currentProvider.options.type); } })); + this._register(this._editorWidget.onDidDispose(() => this._resetContextKeys())); + } + + private _resetContextKeys(): void { + this._accessiblityHelpIsShown.reset(); + this._accessibleViewIsShown.reset(); + this._accessibleViewSupportsNavigation.reset(); + this._accessibleViewVerbosityEnabled.reset(); + this._accessibleViewGoToSymbolSupported.reset(); + this._accessibleViewCurrentProviderId.reset(); } show(provider?: IAccessibleContentProvider, symbol?: IAccessibleViewSymbol, showAccessibleViewHelp?: boolean): void { @@ -186,8 +196,7 @@ class AccessibleView extends Disposable { onHide: () => { if (!showAccessibleViewHelp) { this._currentProvider = undefined; - this._accessibleViewCurrentProviderId.reset(); - this._updateContextKeys(provider!, false); + this._resetContextKeys(); } } }; From 27eb58d046191d391bbf99a18398fdebe39e7996 Mon Sep 17 00:00:00 2001 From: Andrea Mah <31675041+andreamah@users.noreply.github.com> Date: Thu, 24 Aug 2023 14:54:28 -0700 Subject: [PATCH 207/221] Add `preserveInput` for quick search and remove col:line (#191260) Fixes #191258 Fixes #191253 --- .../quickTextSearch/textSearchQuickAccess.ts | 14 ++++++++++---- .../contrib/search/browser/search.contribution.ts | 7 ++++++- src/vs/workbench/services/search/common/search.ts | 3 +++ 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/contrib/search/browser/quickTextSearch/textSearchQuickAccess.ts b/src/vs/workbench/contrib/search/browser/quickTextSearch/textSearchQuickAccess.ts index d01ad5ad73b..6324613fbfd 100644 --- a/src/vs/workbench/contrib/search/browser/quickTextSearch/textSearchQuickAccess.ts +++ b/src/vs/workbench/contrib/search/browser/quickTextSearch/textSearchQuickAccess.ts @@ -15,9 +15,9 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { ILabelService } from 'vs/platform/label/common/label'; import { WorkbenchCompressibleObjectTree, getSelectionKeyboardEvent } from 'vs/platform/list/browser/listService'; import { FastAndSlowPicks, IPickerQuickAccessItem, PickerQuickAccessProvider, Picks } from 'vs/platform/quickinput/browser/pickerQuickAccess'; +import { DefaultQuickAccessFilterValue } from 'vs/platform/quickinput/common/quickAccess'; import { IKeyMods, IQuickPickItem, IQuickPickSeparator } from 'vs/platform/quickinput/common/quickInput'; import { IWorkspaceContextService, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; -import { IWorkbenchQuickAccessConfiguration } from 'vs/workbench/browser/quickaccess'; import { IWorkbenchEditorConfiguration } from 'vs/workbench/common/editor'; import { IViewsService } from 'vs/workbench/common/views'; import { searchDetailsIcon, searchOpenInFileIcon } from 'vs/workbench/contrib/search/browser/searchIcons'; @@ -78,16 +78,23 @@ export class TextSearchQuickAccess extends PickerQuickAccessProvider().workbench?.editor; const searchConfig = this._configurationService.getValue().search; - const quickAccessConfig = this._configurationService.getValue().workbench.quickOpen; return { openEditorPinned: !editorConfig?.enablePreviewFromQuickOpen || !editorConfig?.enablePreview, - preserveInput: quickAccessConfig.preserveInput, + preserveInput: searchConfig.experimental.quickAccess.preserveInput, maxResults: searchConfig.maxResults, smartCase: searchConfig.smartCase, }; } + get defaultFilterValue(): DefaultQuickAccessFilterValue | undefined { + if (this.configuration.preserveInput) { + return DefaultQuickAccessFilterValue.LAST; + } + + return undefined; + } + private doSearch(contentPattern: string, token: CancellationToken): { syncResults: FileMatch[]; asyncResults: Promise; @@ -195,7 +202,6 @@ export class TextSearchQuickAccess extends PickerQuickAccessProvider { await this.handleAccept(fileMatch, { diff --git a/src/vs/workbench/contrib/search/browser/search.contribution.ts b/src/vs/workbench/contrib/search/browser/search.contribution.ts index 2f9b6d54d73..a2f41a98fac 100644 --- a/src/vs/workbench/contrib/search/browser/search.contribution.ts +++ b/src/vs/workbench/contrib/search/browser/search.contribution.ts @@ -376,7 +376,12 @@ configurationRegistry.registerConfiguration({ type: 'boolean', description: nls.localize('search.experimental.closedNotebookResults', "Show notebook editor rich content results for closed notebooks. Please refresh your search results after changing this setting."), default: false - } + }, + 'search.experimental.quickAccess.preserveInput': { + 'type': 'boolean', + 'description': nls.localize('search.experimental.quickAccess.preserveInput', "Controls whether the last typed input to Quick Search should be restored when opening it the next time."), + 'default': false + }, } }); diff --git a/src/vs/workbench/services/search/common/search.ts b/src/vs/workbench/services/search/common/search.ts index caded264a85..6935850b671 100644 --- a/src/vs/workbench/services/search/common/search.ts +++ b/src/vs/workbench/services/search/common/search.ts @@ -414,6 +414,9 @@ export interface ISearchConfigurationProperties { defaultViewMode: ViewMode; experimental: { closedNotebookRichContentResults: boolean; + quickAccess: { + preserveInput: boolean; + }; }; } From 885ebcd9b44968dbad137ff21102a39341cba303 Mon Sep 17 00:00:00 2001 From: Henning Dieterichs Date: Thu, 24 Aug 2023 22:25:19 +0200 Subject: [PATCH 208/221] Fixes #185781 --- .../diffEditorWidget2/diffEditorWidget2.ts | 8 +- .../widget/diffEditorWidget2/outlineModel.ts | 384 ++++++++++++++++++ .../diffEditorWidget2/unchangedRanges.ts | 104 ++++- 3 files changed, 480 insertions(+), 16 deletions(-) create mode 100644 src/vs/editor/browser/widget/diffEditorWidget2/outlineModel.ts diff --git a/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2.ts b/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2.ts index 280c2bb7b9a..b8c42ae717f 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2.ts @@ -157,7 +157,9 @@ export class DiffEditorWidget2 extends DelegatingEditor implements IDiffEditor { this._register(autorunWithStore((reader, store) => { /** @description UnchangedRangesFeature */ - this.unchangedRangesFeature = store.add(new (readHotReloadableExport(UnchangedRangesFeature, reader))(this._editors, this._diffModel, this._options)); + this.unchangedRangesFeature = store.add( + this._instantiationService.createInstance(readHotReloadableExport(UnchangedRangesFeature, reader), this._editors, this._diffModel, this._options) + ); })); this._register(autorunWithStore((reader, store) => { @@ -178,7 +180,9 @@ export class DiffEditorWidget2 extends DelegatingEditor implements IDiffEditor { this._register(autorunWithStore((reader, store) => { /** @description OverviewRulerPart */ - store.add(this._instantiationService.createInstance(readHotReloadableExport(OverviewRulerPart, reader), this._editors, + store.add(this._instantiationService.createInstance( + readHotReloadableExport(OverviewRulerPart, reader), + this._editors, this.elements.root, this._diffModel, this._rootSizeObserver.width, diff --git a/src/vs/editor/browser/widget/diffEditorWidget2/outlineModel.ts b/src/vs/editor/browser/widget/diffEditorWidget2/outlineModel.ts new file mode 100644 index 00000000000..cd12277b82c --- /dev/null +++ b/src/vs/editor/browser/widget/diffEditorWidget2/outlineModel.ts @@ -0,0 +1,384 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { binarySearch, coalesceInPlace, equals } from 'vs/base/common/arrays'; +import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation'; +import { onUnexpectedExternalError } from 'vs/base/common/errors'; +import { Iterable } from 'vs/base/common/iterator'; +import { commonPrefixLength } from 'vs/base/common/strings'; +import { URI } from 'vs/base/common/uri'; +import { IPosition, Position } from 'vs/editor/common/core/position'; +import { IRange, Range } from 'vs/editor/common/core/range'; +import { LanguageFeatureRegistry } from 'vs/editor/common/languageFeatureRegistry'; +import { DocumentSymbol, DocumentSymbolProvider } from 'vs/editor/common/languages'; +import { ITextModel } from 'vs/editor/common/model'; +import { MarkerSeverity } from 'vs/platform/markers/common/markers'; + +// TODO@hediet: These classes are copied from outlineModel.ts because of layering issues. +// Because these classes just depend on the DocumentSymbolProvider (which is in the core editor), +// they should be moved to the core editor as well. + +export abstract class TreeElement { + + abstract id: string; + abstract children: Map; + abstract parent: TreeElement | undefined; + + remove(): void { + this.parent?.children.delete(this.id); + } + + static findId(candidate: DocumentSymbol | string, container: TreeElement): string { + // complex id-computation which contains the origin/extension, + // the parent path, and some dedupe logic when names collide + let candidateId: string; + if (typeof candidate === 'string') { + candidateId = `${container.id}/${candidate}`; + } else { + candidateId = `${container.id}/${candidate.name}`; + if (container.children.get(candidateId) !== undefined) { + candidateId = `${container.id}/${candidate.name}_${candidate.range.startLineNumber}_${candidate.range.startColumn}`; + } + } + + let id = candidateId; + for (let i = 0; container.children.get(id) !== undefined; i++) { + id = `${candidateId}_${i}`; + } + + return id; + } + + static getElementById(id: string, element: TreeElement): TreeElement | undefined { + if (!id) { + return undefined; + } + const len = commonPrefixLength(id, element.id); + if (len === id.length) { + return element; + } + if (len < element.id.length) { + return undefined; + } + for (const [, child] of element.children) { + const candidate = TreeElement.getElementById(id, child); + if (candidate) { + return candidate; + } + } + return undefined; + } + + static size(element: TreeElement): number { + let res = 1; + for (const [, child] of element.children) { + res += TreeElement.size(child); + } + return res; + } + + static empty(element: TreeElement): boolean { + return element.children.size === 0; + } +} + +export interface IOutlineMarker { + startLineNumber: number; + startColumn: number; + endLineNumber: number; + endColumn: number; + severity: MarkerSeverity; +} + +export class OutlineElement extends TreeElement { + + children = new Map(); + marker: { count: number; topSev: MarkerSeverity } | undefined; + + constructor( + readonly id: string, + public parent: TreeElement | undefined, + readonly symbol: DocumentSymbol + ) { + super(); + } +} + +export class OutlineGroup extends TreeElement { + + children = new Map(); + + constructor( + readonly id: string, + public parent: TreeElement | undefined, + readonly label: string, + readonly order: number, + ) { + super(); + } + + getItemEnclosingPosition(position: IPosition): OutlineElement | undefined { + return position ? this._getItemEnclosingPosition(position, this.children) : undefined; + } + + private _getItemEnclosingPosition(position: IPosition, children: Map): OutlineElement | undefined { + for (const [, item] of children) { + if (!item.symbol.range || !Range.containsPosition(item.symbol.range, position)) { + continue; + } + return this._getItemEnclosingPosition(position, item.children) || item; + } + return undefined; + } + + updateMarker(marker: IOutlineMarker[]): void { + for (const [, child] of this.children) { + this._updateMarker(marker, child); + } + } + + private _updateMarker(markers: IOutlineMarker[], item: OutlineElement): void { + item.marker = undefined; + + // find the proper start index to check for item/marker overlap. + const idx = binarySearch(markers, item.symbol.range, Range.compareRangesUsingStarts); + let start: number; + if (idx < 0) { + start = ~idx; + if (start > 0 && Range.areIntersecting(markers[start - 1], item.symbol.range)) { + start -= 1; + } + } else { + start = idx; + } + + const myMarkers: IOutlineMarker[] = []; + let myTopSev: MarkerSeverity | undefined; + + for (; start < markers.length && Range.areIntersecting(item.symbol.range, markers[start]); start++) { + // remove markers intersecting with this outline element + // and store them in a 'private' array. + const marker = markers[start]; + myMarkers.push(marker); + (markers as Array)[start] = undefined; + if (!myTopSev || marker.severity > myTopSev) { + myTopSev = marker.severity; + } + } + + // Recurse into children and let them match markers that have matched + // this outline element. This might remove markers from this element and + // therefore we remember that we have had markers. That allows us to render + // the dot, saying 'this element has children with markers' + for (const [, child] of item.children) { + this._updateMarker(myMarkers, child); + } + + if (myTopSev) { + item.marker = { + count: myMarkers.length, + topSev: myTopSev + }; + } + + coalesceInPlace(markers); + } +} + +export class OutlineModel extends TreeElement { + + static create(registry: LanguageFeatureRegistry, textModel: ITextModel, token: CancellationToken): Promise { + + const cts = new CancellationTokenSource(token); + const result = new OutlineModel(textModel.uri); + const provider = registry.ordered(textModel); + const promises = provider.map((provider, index) => { + + const id = TreeElement.findId(`provider_${index}`, result); + const group = new OutlineGroup(id, result, provider.displayName ?? 'Unknown Outline Provider', index); + + + return Promise.resolve(provider.provideDocumentSymbols(textModel, cts.token)).then(result => { + for (const info of result || []) { + OutlineModel._makeOutlineElement(info, group); + } + return group; + }, err => { + onUnexpectedExternalError(err); + return group; + }).then(group => { + if (!TreeElement.empty(group)) { + result._groups.set(id, group); + } else { + group.remove(); + } + }); + }); + + const listener = registry.onDidChange(() => { + const newProvider = registry.ordered(textModel); + if (!equals(newProvider, provider)) { + cts.cancel(); + } + }); + + return Promise.all(promises).then(() => { + if (cts.token.isCancellationRequested && !token.isCancellationRequested) { + return OutlineModel.create(registry, textModel, token); + } else { + return result._compact(); + } + }).finally(() => { + listener.dispose(); + }); + } + + private static _makeOutlineElement(info: DocumentSymbol, container: OutlineGroup | OutlineElement): void { + const id = TreeElement.findId(info, container); + const res = new OutlineElement(id, container, info); + if (info.children) { + for (const childInfo of info.children) { + OutlineModel._makeOutlineElement(childInfo, res); + } + } + container.children.set(res.id, res); + } + + static get(element: TreeElement | undefined): OutlineModel | undefined { + while (element) { + if (element instanceof OutlineModel) { + return element; + } + element = element.parent; + } + return undefined; + } + + readonly id = 'root'; + readonly parent = undefined; + + protected _groups = new Map(); + children = new Map(); + + protected constructor(readonly uri: URI) { + super(); + + this.id = 'root'; + this.parent = undefined; + } + + private _compact(): this { + let count = 0; + for (const [key, group] of this._groups) { + if (group.children.size === 0) { // empty + this._groups.delete(key); + } else { + count += 1; + } + } + if (count !== 1) { + // + this.children = this._groups; + } else { + // adopt all elements of the first group + const group = Iterable.first(this._groups.values())!; + for (const [, child] of group.children) { + child.parent = this; + this.children.set(child.id, child); + } + } + return this; + } + + merge(other: OutlineModel): boolean { + if (this.uri.toString() !== other.uri.toString()) { + return false; + } + if (this._groups.size !== other._groups.size) { + return false; + } + this._groups = other._groups; + this.children = other.children; + return true; + } + + getItemEnclosingPosition(position: IPosition, context?: OutlineElement): OutlineElement | undefined { + + let preferredGroup: OutlineGroup | undefined; + if (context) { + let candidate = context.parent; + while (candidate && !preferredGroup) { + if (candidate instanceof OutlineGroup) { + preferredGroup = candidate; + } + candidate = candidate.parent; + } + } + + let result: OutlineElement | undefined = undefined; + for (const [, group] of this._groups) { + result = group.getItemEnclosingPosition(position); + if (result && (!preferredGroup || preferredGroup === group)) { + break; + } + } + return result; + } + + getItemById(id: string): TreeElement | undefined { + return TreeElement.getElementById(id, this); + } + + updateMarker(marker: IOutlineMarker[]): void { + // sort markers by start range so that we can use + // outline element starts for quicker look up + marker.sort(Range.compareRangesUsingStarts); + + for (const [, group] of this._groups) { + group.updateMarker(marker.slice(0)); + } + } + + getTopLevelSymbols(): DocumentSymbol[] { + const roots: DocumentSymbol[] = []; + for (const child of this.children.values()) { + if (child instanceof OutlineElement) { + roots.push(child.symbol); + } else { + roots.push(...Iterable.map(child.children.values(), child => child.symbol)); + } + } + return roots.sort((a, b) => Range.compareRangesUsingStarts(a.range, b.range)); + } + + asListOfDocumentSymbols(): DocumentSymbol[] { + const roots = this.getTopLevelSymbols(); + const bucket: DocumentSymbol[] = []; + OutlineModel._flattenDocumentSymbols(bucket, roots, ''); + return bucket.sort((a, b) => + Position.compare(Range.getStartPosition(a.range), Range.getStartPosition(b.range)) || Position.compare(Range.getEndPosition(b.range), Range.getEndPosition(a.range)) + ); + } + + private static _flattenDocumentSymbols(bucket: DocumentSymbol[], entries: DocumentSymbol[], overrideContainerLabel: string): void { + for (const entry of entries) { + bucket.push({ + kind: entry.kind, + tags: entry.tags, + name: entry.name, + detail: entry.detail, + containerName: entry.containerName || overrideContainerLabel, + range: entry.range, + selectionRange: entry.selectionRange, + children: undefined, // we flatten it... + }); + + // Recurse over children + if (entry.children) { + OutlineModel._flattenDocumentSymbols(bucket, entry.children, entry.name); + } + } + } +} diff --git a/src/vs/editor/browser/widget/diffEditorWidget2/unchangedRanges.ts b/src/vs/editor/browser/widget/diffEditorWidget2/unchangedRanges.ts index 7272f56b11f..b3ac905331d 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget2/unchangedRanges.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget2/unchangedRanges.ts @@ -4,34 +4,49 @@ *--------------------------------------------------------------------------------------------*/ import { $, addDisposableListener, h, reset } from 'vs/base/browser/dom'; -import { renderLabelWithIcons } from 'vs/base/browser/ui/iconLabel/iconLabels'; +import { renderIcon, renderLabelWithIcons } from 'vs/base/browser/ui/iconLabel/iconLabels'; +import { compareBy, numberComparator, reverseOrder } from 'vs/base/common/arrays'; +import { CancellationTokenSource } from 'vs/base/common/cancellation'; import { Codicon } from 'vs/base/common/codicons'; +import { Event } from 'vs/base/common/event'; import { MarkdownString } from 'vs/base/common/htmlContent'; import { Disposable } from 'vs/base/common/lifecycle'; -import { IObservable, autorun, derived, derivedWithStore, observableFromEvent, transaction } from 'vs/base/common/observable'; +import { IObservable, IReader, autorun, autorunWithStore, derived, derivedWithStore, observableFromEvent, observableSignalFromEvent, observableValue, transaction } from 'vs/base/common/observable'; import { ThemeIcon } from 'vs/base/common/themables'; import { isDefined } from 'vs/base/common/types'; import { ICodeEditor, IViewZone } from 'vs/editor/browser/editorBrowser'; import { DiffEditorEditors } from 'vs/editor/browser/widget/diffEditorWidget2/diffEditorEditors'; import { DiffEditorOptions } from 'vs/editor/browser/widget/diffEditorWidget2/diffEditorOptions'; import { DiffEditorViewModel, UnchangedRegion } from 'vs/editor/browser/widget/diffEditorWidget2/diffEditorViewModel'; +import { OutlineModel } from 'vs/editor/browser/widget/diffEditorWidget2/outlineModel'; import { PlaceholderViewZone, ViewZoneOverlayWidget, applyObservableDecorations, applyStyle, applyViewZones } from 'vs/editor/browser/widget/diffEditorWidget2/utils'; import { EditorOption } from 'vs/editor/common/config/editorOptions'; import { LineRange } from 'vs/editor/common/core/lineRange'; import { Position } from 'vs/editor/common/core/position'; import { Range } from 'vs/editor/common/core/range'; import { CursorChangeReason } from 'vs/editor/common/cursorEvents'; -import { IModelDecorationOptions, IModelDeltaDecoration } from 'vs/editor/common/model'; +import { SymbolKind, SymbolKinds } from 'vs/editor/common/languages'; +import { IModelDecorationOptions, IModelDeltaDecoration, ITextModel } from 'vs/editor/common/model'; +import { ILanguageFeaturesService } from 'vs/editor/common/services/languageFeatures'; import { localize } from 'vs/nls'; export class UnchangedRangesFeature extends Disposable { private _isUpdatingViewZones = false; public get isUpdatingViewZones(): boolean { return this._isUpdatingViewZones; } + private readonly _modifiedModel = observableFromEvent(this._editors.modified.onDidChangeModel, () => this._editors.modified.getModel()); + + private readonly _modifiedOutlineSource = derivedWithStore('modified outline source', (reader, store) => { + const m = this._modifiedModel.read(reader); + if (!m) { return undefined; } + return store.add(new OutlineSource(this._languageFeaturesService, m)); + }); + constructor( private readonly _editors: DiffEditorEditors, private readonly _diffModel: IObservable, private readonly _options: DiffEditorOptions, + @ILanguageFeaturesService private readonly _languageFeaturesService: ILanguageFeaturesService, ) { super(); @@ -66,6 +81,9 @@ export class UnchangedRangesFeature extends Disposable { const modViewZones: IViewZone[] = []; const sideBySide = this._options.renderSideBySide.read(reader); + const modifiedOutlineSource = this._modifiedOutlineSource.read(reader); + if (!modifiedOutlineSource) { return { origViewZones, modViewZones }; } + const curUnchangedRegions = unchangedRegions.read(reader); for (const r of curUnchangedRegions) { if (r.shouldHideControls(reader)) { @@ -76,13 +94,13 @@ export class UnchangedRangesFeature extends Disposable { const d = derived(reader => /** @description hiddenOriginalRangeStart */ r.getHiddenOriginalRange(reader).startLineNumber - 1); const origVz = new PlaceholderViewZone(d, 24); origViewZones.push(origVz); - store.add(new CollapsedCodeOverlayWidget(this._editors.original, origVz, r, !sideBySide)); + store.add(new CollapsedCodeOverlayWidget(this._editors.original, origVz, r, !sideBySide, modifiedOutlineSource)); } { const d = derived(reader => /** @description hiddenModifiedRangeStart */ r.getHiddenModifiedRange(reader).startLineNumber - 1); const modViewZone = new PlaceholderViewZone(d, 24); modViewZones.push(modViewZone); - store.add(new CollapsedCodeOverlayWidget(this._editors.modified, modViewZone, r, false)); + store.add(new CollapsedCodeOverlayWidget(this._editors.modified, modViewZone, r, false, modifiedOutlineSource)); } } @@ -177,6 +195,57 @@ export class UnchangedRangesFeature extends Disposable { } } +class DisposableCancellationTokenSource extends CancellationTokenSource { + public override dispose() { + super.dispose(true); + } +} + +class OutlineSource extends Disposable { + private readonly _currentModel = observableValue('current model', undefined); + + constructor( + @ILanguageFeaturesService private readonly _languageFeaturesService: ILanguageFeaturesService, + private readonly _textModel: ITextModel, + ) { + super(); + + const documentSymbolProviderChanged = observableSignalFromEvent( + 'documentSymbolProvider.onDidChange', + this._languageFeaturesService.documentSymbolProvider.onDidChange + ); + + const textModelChanged = observableSignalFromEvent( + '_textModel.onDidChangeContent', + Event.debounce(e => this._textModel.onDidChangeContent(e), () => undefined, 100) + ); + + this._register(autorunWithStore(async (reader, store) => { + documentSymbolProviderChanged.read(reader); + textModelChanged.read(reader); + + const src = store.add(new DisposableCancellationTokenSource()); + const model = await OutlineModel.create( + this._languageFeaturesService.documentSymbolProvider, + this._textModel, + src.token, + ); + if (store.isDisposed) { return; } + + this._currentModel.set(model, undefined); + })); + } + + public getBreadcrumbItems(startRange: LineRange, reader: IReader): { name: string; kind: SymbolKind }[] { + const m = this._currentModel.read(reader); + if (!m) { return []; } + const symbols = m.asListOfDocumentSymbols() + .filter(s => startRange.contains(s.range.startLineNumber) && !startRange.contains(s.range.endLineNumber)); + symbols.sort(reverseOrder(compareBy(s => s.range.endLineNumber - s.range.startLineNumber, numberComparator))); + return symbols.map(s => ({ name: s.name, kind: s.kind })); + } +} + class CollapsedCodeOverlayWidget extends ViewZoneOverlayWidget { private readonly _nodes = h('div.diff-hidden-lines', [ h('div.top@top', { title: localize('diff.hiddenLines.top', 'Click or drag to show more above') }), @@ -194,6 +263,7 @@ class CollapsedCodeOverlayWidget extends ViewZoneOverlayWidget { _viewZone: PlaceholderViewZone, private readonly _unchangedRegion: UnchangedRegion, private readonly hide: boolean, + private readonly _modifiedOutlineSource: OutlineSource, ) { const root = h('div.diff-hidden-lines-widget'); super(_editor, _viewZone, root.root); @@ -296,19 +366,25 @@ class CollapsedCodeOverlayWidget extends ViewZoneOverlayWidget { children.push($('span', { title: linesHiddenText }, linesHiddenText)); } - // TODO@hediet implement breadcrumbs for collapsed regions - /* - if (_unchangedRegion.originalLineNumber === 48) { + const range = this._unchangedRegion.getHiddenModifiedRange(reader); + const items = this._modifiedOutlineSource.getBreadcrumbItems(range, reader); + + if (items.length > 0) { children.push($('span', undefined, '\u00a0|\u00a0')); - children.push($('span', { title: 'test' }, ...renderLabelWithIcons('$(symbol-class) DiffEditorWidget2'))); - } else if (_unchangedRegion.originalLineNumber === 88) { - children.push($('span', undefined, '\u00a0|\u00a0')); - children.push($('span', { title: 'test' }, ...renderLabelWithIcons('$(symbol-constructor) constructor'))); + + let isFirst = true; + for (const item of items) { + if (!isFirst) { + children.push($('span', {}, ' ', renderIcon(Codicon.chevronRight), ' ')); + } + + const icon = SymbolKinds.toIcon(item.kind); + children.push($('span', {}, renderIcon(icon), ' ', item.name)); + isFirst = false; + } } - */ reset(this._nodes.others, ...children); - })); } } From 16cae5ea488e45d183859c3b5dcca7e7af46ae83 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Thu, 24 Aug 2023 15:35:08 -0700 Subject: [PATCH 209/221] Feedback --- src/vs/workbench/api/common/extHostTerminalService.ts | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/vs/workbench/api/common/extHostTerminalService.ts b/src/vs/workbench/api/common/extHostTerminalService.ts index ecc9e00556f..58bc387e600 100644 --- a/src/vs/workbench/api/common/extHostTerminalService.ts +++ b/src/vs/workbench/api/common/extHostTerminalService.ts @@ -24,7 +24,6 @@ import { ThemeColor } from 'vs/base/common/themables'; import { Promises } from 'vs/base/common/async'; import { EditorGroupColumn } from 'vs/workbench/services/editor/common/editorGroupColumn'; import { TerminalQuickFix, ViewColumn } from 'vs/workbench/api/common/extHostTypeConverters'; -import { checkProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions'; import { IExtHostCommands } from 'vs/workbench/api/common/extHostCommands'; export interface IExtHostTerminalService extends ExtHostTerminalServiceShape, IDisposable { @@ -858,7 +857,7 @@ export abstract class BaseExtHostTerminalService extends Disposable implements I public getEnvironmentVariableCollection(extension: IExtensionDescription): IEnvironmentVariableCollection { let collection = this._environmentVariableCollections.get(extension.identifier.value); if (!collection) { - collection = new UnifiedEnvironmentVariableCollection(extension); + collection = new UnifiedEnvironmentVariableCollection(); this._setEnvironmentVariableCollection(extension.identifier.value, collection); } return collection.getScopedEnvironmentVariableCollection(undefined); @@ -873,7 +872,7 @@ export abstract class BaseExtHostTerminalService extends Disposable implements I public $initEnvironmentVariableCollections(collections: [string, ISerializableEnvironmentVariableCollection][]): void { collections.forEach(entry => { const extensionIdentifier = entry[0]; - const collection = new UnifiedEnvironmentVariableCollection(undefined, entry[1]); + const collection = new UnifiedEnvironmentVariableCollection(entry[1]); this._setEnvironmentVariableCollection(extensionIdentifier, collection); }); } @@ -918,11 +917,6 @@ class UnifiedEnvironmentVariableCollection { get onDidChangeCollection(): Event { return this._onDidChangeCollection && this._onDidChangeCollection.event; } constructor( - // HACK: Only check proposed options if extension is set (when the collection is not - // restored by serialization). This saves us from getting the extension details and - // shouldn't ever happen since you can only set them initially via the proposed check. - // TODO: This should be removed when the env var extension API(s) are stabilized - private readonly _extension: IExtensionDescription | undefined, serialized?: ISerializableEnvironmentVariableCollection ) { this.map = new Map(serialized); From 99be1c1421fea67ca92ace86a232ba7178592216 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Thu, 24 Aug 2023 15:38:47 -0700 Subject: [PATCH 210/221] Pick up latest TS (#191262) --- extensions/package.json | 2 +- extensions/yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/extensions/package.json b/extensions/package.json index 02a1f822e7d..2b68f668d5b 100644 --- a/extensions/package.json +++ b/extensions/package.json @@ -4,7 +4,7 @@ "license": "MIT", "description": "Dependencies shared by all extensions", "dependencies": { - "typescript": "^5.2.1-rc" + "typescript": "^5.2.2" }, "scripts": { "postinstall": "node ./postinstall.mjs" diff --git a/extensions/yarn.lock b/extensions/yarn.lock index 08ae5fb06c3..b704d5f8a28 100644 --- a/extensions/yarn.lock +++ b/extensions/yarn.lock @@ -228,10 +228,10 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" -typescript@^5.2.1-rc: - version "5.2.1-rc" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.2.1-rc.tgz#9cf33ff6bc39ba9e1fa59761124f596ecf5e0c07" - integrity sha512-gsOdmedQZEWLrYhNqHuzPmcV+4wX7UujzYqszDC5mVMjcN6Nm7lN2eAtndmjWl24aGdAwJqL2ooywkxpaTx8QQ== +typescript@^5.2.2: + version "5.2.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.2.2.tgz#5ebb5e5a5b75f085f22bc3f8460fba308310fa78" + integrity sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w== vscode-grammar-updater@^1.1.0: version "1.1.0" From f9db0056398ae3f24ebd0a6b38be13b212f95c6e Mon Sep 17 00:00:00 2001 From: Tyler James Leonhardt Date: Thu, 24 Aug 2023 15:53:44 -0700 Subject: [PATCH 211/221] Bump height of quick chat to 900 max (#191265) --- src/vs/workbench/contrib/chat/browser/chatQuick.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/chat/browser/chatQuick.ts b/src/vs/workbench/contrib/chat/browser/chatQuick.ts index 6e30b77907b..4ddde25c475 100644 --- a/src/vs/workbench/contrib/chat/browser/chatQuick.ts +++ b/src/vs/workbench/contrib/chat/browser/chatQuick.ts @@ -149,7 +149,7 @@ class QuickChat extends Disposable { })); this.widget.render(parent); this.widget.setVisible(true); - this.widget.setDynamicChatTreeItemLayout(2, 600); + this.widget.setDynamicChatTreeItemLayout(2, 900); this.updateModel(); if (this._currentQuery) { this.widget.inputEditor.setSelection({ From 37e5ca3fa5eb7db431e74de62ac0b394c5fa70d4 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Thu, 24 Aug 2023 16:25:04 -0700 Subject: [PATCH 212/221] Pick up latest TS for building VS Code (#191264) --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 2e5dcf01a2e..080af3cecd2 100644 --- a/package.json +++ b/package.json @@ -212,7 +212,7 @@ "ts-loader": "^9.4.2", "ts-node": "^10.9.1", "tsec": "0.2.7", - "typescript": "^5.3.0-dev.20230816", + "typescript": "^5.3.0-dev.20230824", "typescript-formatter": "7.1.0", "underscore": "^1.12.1", "util": "^0.12.4", diff --git a/yarn.lock b/yarn.lock index 5595e14de37..582d6e845a1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10075,10 +10075,10 @@ typescript@^4.7.4: resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.8.4.tgz#c464abca159669597be5f96b8943500b238e60e6" integrity sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ== -typescript@^5.3.0-dev.20230816: - version "5.3.0-dev.20230816" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.3.0-dev.20230816.tgz#409982c629164811db1eb62b365ed2e1b526458d" - integrity sha512-iEOudrx61DsbJn+z2bVX+/FldF7ILAuGwQYO2EvF4F33Q8DUV0KSkiikxUB83VVH8ExkwQHVNdtkr16wd2V71w== +typescript@^5.3.0-dev.20230824: + version "5.3.0-dev.20230824" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.3.0-dev.20230824.tgz#14fc65c14c588363c0d290dbbbda8ae0968fd95b" + integrity sha512-iiUWxGibzrRHEBLDJfVymsvpPKflf3cMrw0oQTMQoguFS2ikNlVlfQWAsYeHqGpRQc77nSQkzsE9rAHNHqvIjw== typical@^4.0.0: version "4.0.0" From cd5b67db5bdcfaae0d191a51a4e22a9cad061903 Mon Sep 17 00:00:00 2001 From: David Dossett Date: Thu, 24 Aug 2023 17:25:55 -0700 Subject: [PATCH 213/221] Tune quick text search heading styles (#191268) --- src/vs/platform/quickinput/browser/media/quickInput.css | 6 ++++++ src/vs/platform/quickinput/browser/quickInputController.ts | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/vs/platform/quickinput/browser/media/quickInput.css b/src/vs/platform/quickinput/browser/media/quickInput.css index 9bb877f9991..f6c76ccd9b5 100644 --- a/src/vs/platform/quickinput/browser/media/quickInput.css +++ b/src/vs/platform/quickinput/browser/media/quickInput.css @@ -318,3 +318,9 @@ .quick-input-list .monaco-list-row.focused .monaco-keybinding-key { background: none; } + +/* Quick input separators as full-row item */ +.quick-input-list .quick-input-list-separator-as-item { + font-weight: 600; + font-size: 12px; +} diff --git a/src/vs/platform/quickinput/browser/quickInputController.ts b/src/vs/platform/quickinput/browser/quickInputController.ts index 0328a6a6ded..f42e1ff78d1 100644 --- a/src/vs/platform/quickinput/browser/quickInputController.ts +++ b/src/vs/platform/quickinput/browser/quickInputController.ts @@ -683,7 +683,7 @@ export class QuickInputController extends Disposable { content.push(`.quick-input-list .quick-input-list-separator { color: ${this.styles.pickerGroup.pickerGroupForeground}; }`); } if (this.styles.pickerGroup.pickerGroupForeground) { - content.push(`.quick-input-list .quick-input-list-separator-as-item { color: ${this.styles.pickerGroup.pickerGroupForeground}; }`); + content.push(`.quick-input-list .quick-input-list-separator-as-item { color: var(--vscode-descriptionForeground); }`); } if (this.styles.keybindingLabel.keybindingLabelBackground || From 083fca132543aa91a7e1de2dc23857d70ea56dd3 Mon Sep 17 00:00:00 2001 From: Raymond Zhao <7199958+rzhao271@users.noreply.github.com> Date: Thu, 24 Aug 2023 17:29:01 -0700 Subject: [PATCH 214/221] Codesign Debian package for PMC API (#191140) * Codesign Debian package for PMC API * Fix directory name * polish displayName --- build/azure-pipelines/linux/product-build-linux.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/build/azure-pipelines/linux/product-build-linux.yml b/build/azure-pipelines/linux/product-build-linux.yml index 2145e588b1c..4641edf7670 100644 --- a/build/azure-pipelines/linux/product-build-linux.yml +++ b/build/azure-pipelines/linux/product-build-linux.yml @@ -312,6 +312,9 @@ steps: continueOnError: true displayName: Download ESRPClient + - script: node build/azure-pipelines/common/sign $(Agent.ToolsDirectory)/esrpclient/*/*/net6.0/esrpcli.dll rpm $(ESRP-PKI) $(esrp-aad-username) $(esrp-aad-password) .build/linux/deb '*.deb' + displayName: Codesign deb + - script: node build/azure-pipelines/common/sign $(Agent.ToolsDirectory)/esrpclient/*/*/net6.0/esrpcli.dll rpm $(ESRP-PKI) $(esrp-aad-username) $(esrp-aad-password) .build/linux/rpm '*.rpm' displayName: Codesign rpm From d8f919404053f3972c8c37797186fc0e6c0b64e9 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 25 Aug 2023 07:23:07 +0200 Subject: [PATCH 215/221] voice - limit media permission to insiders --- src/vs/code/electron-main/app.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index 9c79498b8f5..c6536298e05 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -162,9 +162,9 @@ export class CodeApplication extends Disposable { const isUrlFromWebview = (requestingUrl: string | undefined) => requestingUrl?.startsWith(`${Schemas.vscodeWebview}://`); - const allowedPermissionsInMainFrame = new Set([ - 'media' - ]); + const allowedPermissionsInMainFrame = new Set( + this.productService.quality === 'stable' ? [] : ['media'] + ); const allowedPermissionsInWebview = new Set([ 'clipboard-read', From c908b67da5005bb3c42e9b24af0149d8686d1487 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 25 Aug 2023 07:28:09 +0200 Subject: [PATCH 216/221] voice - actions renames --- .../actions/{chatVoiceInputActions.ts => voiceChatActions.ts} | 2 +- .../contrib/chat/electron-sandbox/chat.contribution.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) rename src/vs/workbench/contrib/chat/electron-sandbox/actions/{chatVoiceInputActions.ts => voiceChatActions.ts} (99%) diff --git a/src/vs/workbench/contrib/chat/electron-sandbox/actions/chatVoiceInputActions.ts b/src/vs/workbench/contrib/chat/electron-sandbox/actions/voiceChatActions.ts similarity index 99% rename from src/vs/workbench/contrib/chat/electron-sandbox/actions/chatVoiceInputActions.ts rename to src/vs/workbench/contrib/chat/electron-sandbox/actions/voiceChatActions.ts index 9ea3b0cde45..a76572d998f 100644 --- a/src/vs/workbench/contrib/chat/electron-sandbox/actions/chatVoiceInputActions.ts +++ b/src/vs/workbench/contrib/chat/electron-sandbox/actions/voiceChatActions.ts @@ -375,7 +375,7 @@ class StopVoiceChatAction extends Action2 { } } -export function registerChatVoiceInputActions() { +export function registerVoiceChatActions() { if (typeof process.env.VSCODE_VOICE_MODULE_PATH === 'string' && product.quality !== 'stable') { // TODO@bpasero package registerAction2(VoiceChatInChatViewAction); registerAction2(QuickVoiceChatAction); diff --git a/src/vs/workbench/contrib/chat/electron-sandbox/chat.contribution.ts b/src/vs/workbench/contrib/chat/electron-sandbox/chat.contribution.ts index 5d49a2d0625..1bd74f66eff 100644 --- a/src/vs/workbench/contrib/chat/electron-sandbox/chat.contribution.ts +++ b/src/vs/workbench/contrib/chat/electron-sandbox/chat.contribution.ts @@ -3,6 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { registerChatVoiceInputActions } from 'vs/workbench/contrib/chat/electron-sandbox/actions/chatVoiceInputActions'; +import { registerVoiceChatActions } from 'vs/workbench/contrib/chat/electron-sandbox/actions/voiceChatActions'; -registerChatVoiceInputActions(); +registerVoiceChatActions(); From 638d83b40472c3868320ff17ed93e809bb34ae31 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 25 Aug 2023 08:56:41 +0200 Subject: [PATCH 217/221] voice - :lipstick: --- .../actions/voiceChatActions.ts | 30 +++++++++---------- .../workbenchVoiceRecognitionService.ts | 17 +++++++---- 2 files changed, 25 insertions(+), 22 deletions(-) diff --git a/src/vs/workbench/contrib/chat/electron-sandbox/actions/voiceChatActions.ts b/src/vs/workbench/contrib/chat/electron-sandbox/actions/voiceChatActions.ts index a76572d998f..8773eff46d5 100644 --- a/src/vs/workbench/contrib/chat/electron-sandbox/actions/voiceChatActions.ts +++ b/src/vs/workbench/contrib/chat/electron-sandbox/actions/voiceChatActions.ts @@ -12,7 +12,7 @@ import { equalsIgnoreCase } from 'vs/base/common/strings'; import { ServicesAccessor } from 'vs/editor/browser/editorExtensions'; import { localize } from 'vs/nls'; import { Action2, MenuId, registerAction2 } from 'vs/platform/actions/common/actions'; -import { IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey'; +import { ContextKeyExpr, IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { spinningLoading } from 'vs/platform/theme/common/iconRegistry'; import { CHAT_CATEGORY } from 'vs/workbench/contrib/chat/browser/actions/chatActions'; @@ -28,9 +28,10 @@ import { isExecuteActionContext } from 'vs/workbench/contrib/chat/browser/action import { ICommandService } from 'vs/platform/commands/common/commands'; import { process } from 'vs/base/parts/sandbox/electron-sandbox/globals'; import product from 'vs/platform/product/common/product'; +import { ActiveEditorContext } from 'vs/workbench/common/contextkeys'; -const CONTEXT_VOICE_CHAT_GETTING_READY = new RawContextKey('voiceChatGettingReady', false, { type: 'boolean', description: localize('voiceChatGettingReady', "True when there is voice input for chat getting ready.") }); -const CONTEXT_VOICE_CHAT_IN_PROGRESS = new RawContextKey('voiceChatInProgress', false, { type: 'boolean', description: localize('voiceChatInProgress', "True when there is voice input for chat in progress.") }); +const CONTEXT_VOICE_CHAT_GETTING_READY = new RawContextKey('voiceChatGettingReady', false, { type: 'boolean', description: localize('voiceChatGettingReady', "True when getting ready for receiving voice input from the microphone.") }); +const CONTEXT_VOICE_CHAT_IN_PROGRESS = new RawContextKey('voiceChatInProgress', false, { type: 'boolean', description: localize('voiceChatInProgress', "True when voice recording from microphone is in progress.") }); interface IVoiceChatSessionController { @@ -94,13 +95,13 @@ class VoiceChatSession { context.focusInput(); const onDidTranscribe = await this.voiceRecognitionService.transcribe(cts.token, { - onDidCancel: () => this.stop() + onDidCancel: () => this.stop(voiceChatSessionId) }); if (cts.token.isCancellationRequested) { return Disposable.None; } - const voiceChatSessionId = this.voiceChatSessionIds++; + const voiceChatSessionId = ++this.voiceChatSessionIds; this.voiceChatGettingReadyKey.set(false); this.voiceChatInProgressKey.set(true); @@ -130,15 +131,9 @@ class VoiceChatSession { } })); - this.currentVoiceChatSession.add(context.onDidAcceptInput(() => { - this.stop(); - })); + this.currentVoiceChatSession.add(context.onDidAcceptInput(() => this.stop(voiceChatSessionId))); - return toDisposable(() => { - if (this.voiceChatSessionIds === voiceChatSessionId) { - this.stop(); - } - }); + return toDisposable(() => this.stop(voiceChatSessionId)); } private isSimilarTranscription(textA: string, textB: string): boolean { @@ -155,11 +150,15 @@ class VoiceChatSession { ); } - stop(): void { + stop(voiceChatSessionId = this.voiceChatSessionIds): void { if (!this.currentVoiceChatSession) { return; } + if (this.voiceChatSessionIds !== voiceChatSessionId) { + return; + } + this.currentVoiceChatSession.dispose(); this.currentVoiceChatSession = undefined; @@ -212,7 +211,7 @@ class InlineVoiceChatAction extends Action2 { original: 'Inline Voice Chat' }, category: CHAT_CATEGORY, - precondition: CONTEXT_PROVIDER_EXISTS, + precondition: ContextKeyExpr.and(CONTEXT_PROVIDER_EXISTS, ActiveEditorContext), f1: true }); } @@ -234,7 +233,6 @@ class InlineVoiceChatAction extends Action2 { const inlineChatSession = controller.run(); const disposable = await VoiceChatSession.getInstance(instantiationService).start(getController(controller)); - inlineChatSession.finally(() => disposable.dispose()); } } diff --git a/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts b/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts index c1863701239..d35dd681f77 100644 --- a/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts +++ b/src/vs/workbench/services/voiceRecognition/electron-sandbox/workbenchVoiceRecognitionService.ts @@ -60,19 +60,24 @@ class VoiceTranscriptionWorkletNode extends AudioWorkletNode { } async start(token: CancellationToken): Promise { + token.onCancellationRequested(() => this.stop()); + const sharedProcessConnection = await this.sharedProcessService.createRawConnection(); - token.onCancellationRequested(() => { - this.port.postMessage('vscode:stopVoiceTranscription'); - this.disconnect(); - }); + if (token.isCancellationRequested) { + this.stop(); + return; + } this.port.postMessage('vscode:startVoiceTranscription', [sharedProcessConnection]); } + + private stop(): void { + this.port.postMessage('vscode:stopVoiceTranscription'); + this.disconnect(); + } } -// TODO@voice -// - add native module test to ensure module loads export class WorkbenchVoiceRecognitionService implements IWorkbenchVoiceRecognitionService { declare readonly _serviceBrand: undefined; From 79506bb29f6248375d44c6faf39dd856fe04a7a2 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 25 Aug 2023 10:22:03 +0200 Subject: [PATCH 218/221] voice - allowLoadingUnsignedLibraries for voice --- src/vs/platform/sharedProcess/electron-main/sharedProcess.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/vs/platform/sharedProcess/electron-main/sharedProcess.ts b/src/vs/platform/sharedProcess/electron-main/sharedProcess.ts index c11fa7d0fc5..70059e1d7fc 100644 --- a/src/vs/platform/sharedProcess/electron-main/sharedProcess.ts +++ b/src/vs/platform/sharedProcess/electron-main/sharedProcess.ts @@ -19,6 +19,7 @@ import { NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtil import { parseSharedProcessDebugPort } from 'vs/platform/environment/node/environmentService'; import { assertIsDefined } from 'vs/base/common/types'; import { SharedProcessChannelConnection, SharedProcessRawConnection, SharedProcessLifecycle } from 'vs/platform/sharedProcess/common/sharedProcess'; +import { IProductService } from 'vs/platform/product/common/productService'; export class SharedProcess extends Disposable { @@ -34,6 +35,7 @@ export class SharedProcess extends Disposable { @ILogService private readonly logService: ILogService, @ILoggerMainService private readonly loggerMainService: ILoggerMainService, @IPolicyService private readonly policyService: IPolicyService, + @IProductService private readonly productService: IProductService ) { super(); @@ -162,7 +164,8 @@ export class SharedProcess extends Disposable { type: 'shared-process', entryPoint: 'vs/code/node/sharedProcess/sharedProcessMain', payload: this.createSharedProcessConfiguration(), - execArgv + execArgv, + allowLoadingUnsignedLibraries: !!process.env.VSCODE_VOICE_MODULE_PATH && this.productService.quality !== 'stable' // TODO@bpasero package }); } From a0ac773aca554cd715b9c04e7e2b26e2da388b75 Mon Sep 17 00:00:00 2001 From: Ladislau Szomoru <3372902+lszomoru@users.noreply.github.com> Date: Fri, 25 Aug 2023 12:01:37 +0200 Subject: [PATCH 219/221] Git - fix issue with smart commit and dirty documents (#191300) --- extensions/git/src/commands.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/extensions/git/src/commands.ts b/extensions/git/src/commands.ts index af40853e27e..704a4fa47fd 100644 --- a/extensions/git/src/commands.ts +++ b/extensions/git/src/commands.ts @@ -1783,12 +1783,17 @@ export class CommandCenter { const message = documents.length === 1 ? l10n.t('The following file has unsaved changes which won\'t be included in the commit if you proceed: {0}.\n\nWould you like to save it before committing?', path.basename(documents[0].uri.fsPath)) : l10n.t('There are {0} unsaved files.\n\nWould you like to save them before committing?', documents.length); - const saveAndCommit = l10n.t('Save All & Commit'); - const commit = l10n.t('Commit Staged Changes'); + const saveAndCommit = l10n.t('Save All & Commit Changes'); + const commit = l10n.t('Commit Changes'); const pick = await window.showWarningMessage(message, { modal: true }, saveAndCommit, commit); if (pick === saveAndCommit) { await Promise.all(documents.map(d => d.save())); + + // After saving the dirty documents, if there are any documents that are part of the + // index group we have to add them back in order for the saved changes to be committed + documents = documents + .filter(d => repository.indexGroup.resourceStates.some(s => pathEquals(s.resourceUri.fsPath, d.uri.fsPath))); await repository.add(documents.map(d => d.uri)); noStagedChanges = repository.indexGroup.resourceStates.length === 0; From 85f166e05360f40ff9c97cbe5255375f0d428f39 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 25 Aug 2023 15:04:59 +0200 Subject: [PATCH 220/221] voice - use `LimitedQueue` to prevent parallel transcriptions (#191311) --- src/vs/base/common/async.ts | 116 +++++++++----- src/vs/base/test/common/async.test.ts | 150 +++++++++++------- .../sharedProcess/contrib/voiceTranscriber.ts | 25 ++- .../textfile/common/textFileEditorModel.ts | 36 ++--- .../common/storedFileWorkingCopy.ts | 36 ++--- 5 files changed, 215 insertions(+), 148 deletions(-) diff --git a/src/vs/base/common/async.ts b/src/vs/base/common/async.ts index 6b87b06b21a..152a6af7e4e 100644 --- a/src/vs/base/common/async.ts +++ b/src/vs/base/common/async.ts @@ -682,6 +682,31 @@ export class Queue extends Limiter { } } +/** + * Same as `Queue`, ensures that only 1 task is executed at the same time. The difference to `Queue` is that + * there is only 1 task about to be scheduled next. As such, calling `queue` while a task is executing will + * replace the currently queued task until it executes. + * + * As such, the returned promise may not be from the factory that is passed in but from the next factory that + * is running after having called `queue`. + */ +export class LimitedQueue { + + private readonly sequentializer = new TaskSequentializer(); + + private tasks = 0; + + queue(factory: ITask>): Promise { + if (!this.sequentializer.isRunning()) { + return this.sequentializer.run(this.tasks++, factory()); + } + + return this.sequentializer.queue(() => { + return this.sequentializer.run(this.tasks++, factory()); + }); + } +} + /** * A helper to organize queues per resource. The ResourceQueue makes sure to manage queues per resource * by disposing them once the queue is empty. @@ -1267,83 +1292,92 @@ export async function retry(task: ITask>, delay: number, retries: //#region Task Sequentializer -interface IPendingTask { +interface IRunningTask { readonly taskId: number; readonly cancel: () => void; readonly promise: Promise; } -interface INextTask { +interface IQueuedTask { readonly promise: Promise; readonly promiseResolve: () => void; readonly promiseReject: (error: Error) => void; - run: () => Promise; + run: ITask>; } -export interface ITaskSequentializerWithPendingTask { - readonly pending: Promise; +export interface ITaskSequentializerWithRunningTask { + readonly running: Promise; } -export interface ITaskSequentializerWithNextTask { - readonly next: INextTask; +export interface ITaskSequentializerWithQueuedTask { + readonly queued: IQueuedTask; } +/** + * @deprecated use `LimitedQueue` instead for an easier to use API + */ export class TaskSequentializer { - private _pending?: IPendingTask; - private _next?: INextTask; + private _running?: IRunningTask; + private _queued?: IQueuedTask; - hasPending(taskId?: number): this is ITaskSequentializerWithPendingTask { + isRunning(taskId?: number): this is ITaskSequentializerWithRunningTask { if (typeof taskId === 'number') { - return this._pending?.taskId === taskId; + return this._running?.taskId === taskId; } - return !!this._pending; + return !!this._running; } - get pending(): Promise | undefined { - return this._pending?.promise; + get running(): Promise | undefined { + return this._running?.promise; } - cancelPending(): void { - this._pending?.cancel(); + cancelRunning(): void { + this._running?.cancel(); } - setPending(taskId: number, promise: Promise, onCancel?: () => void,): Promise { - this._pending = { taskId, cancel: () => onCancel?.(), promise }; + run(taskId: number, promise: Promise, onCancel?: () => void,): Promise { + this._running = { taskId, cancel: () => onCancel?.(), promise }; - promise.then(() => this.donePending(taskId), () => this.donePending(taskId)); + promise.then(() => this.doneRunning(taskId), () => this.doneRunning(taskId)); return promise; } - private donePending(taskId: number): void { - if (this._pending && taskId === this._pending.taskId) { + private doneRunning(taskId: number): void { + if (this._running && taskId === this._running.taskId) { - // only set pending to done if the promise finished that is associated with that taskId - this._pending = undefined; + // only set running to done if the promise finished that is associated with that taskId + this._running = undefined; - // schedule the next task now that we are free if we have any - this.triggerNext(); + // schedule the queued task now that we are free if we have any + this.runQueued(); } } - private triggerNext(): void { - if (this._next) { - const next = this._next; - this._next = undefined; + private runQueued(): void { + if (this._queued) { + const queued = this._queued; + this._queued = undefined; - // Run next task and complete on the associated promise - next.run().then(next.promiseResolve, next.promiseReject); + // Run queued task and complete on the associated promise + queued.run().then(queued.promiseResolve, queued.promiseReject); } } - setNext(run: () => Promise): Promise { + /** + * Note: the promise to schedule as next run MUST itself call `run`. + * Otherwise, this sequentializer will report `false` for `isRunning` + * even when this task is running. Missing this detail means that + * suddenly multiple tasks will run in parallel. + */ + queue(run: ITask>): Promise { - // this is our first next task, so we create associated promise with it + // this is our first queued task, so we create associated promise with it // so that we can return a promise that completes when the task has // completed. - if (!this._next) { + if (!this._queued) { let promiseResolve: () => void; let promiseReject: (error: Error) => void; const promise = new Promise((resolve, reject) => { @@ -1351,7 +1385,7 @@ export class TaskSequentializer { promiseReject = reject; }); - this._next = { + this._queued = { run, promise, promiseResolve: promiseResolve!, @@ -1359,20 +1393,20 @@ export class TaskSequentializer { }; } - // we have a previous next task, just overwrite it + // we have a previous queued task, just overwrite it else { - this._next.run = run; + this._queued.run = run; } - return this._next.promise; + return this._queued.promise; } - hasNext(): this is ITaskSequentializerWithNextTask { - return !!this._next; + hasQueued(): this is ITaskSequentializerWithQueuedTask { + return !!this._queued; } async join(): Promise { - return this._next?.promise ?? this._pending?.promise; + return this._queued?.promise ?? this._running?.promise; } } diff --git a/src/vs/base/test/common/async.test.ts b/src/vs/base/test/common/async.test.ts index 144c119389a..467708aa2c2 100644 --- a/src/vs/base/test/common/async.test.ts +++ b/src/vs/base/test/common/async.test.ts @@ -664,119 +664,119 @@ suite('Async', () => { }); suite('TaskSequentializer', () => { - test('pending basics', async function () { + test('execution basics', async function () { const sequentializer = new async.TaskSequentializer(); - assert.ok(!sequentializer.hasPending()); - assert.ok(!sequentializer.hasNext()); - assert.ok(!sequentializer.hasPending(2323)); - assert.ok(!sequentializer.pending); + assert.ok(!sequentializer.isRunning()); + assert.ok(!sequentializer.hasQueued()); + assert.ok(!sequentializer.isRunning(2323)); + assert.ok(!sequentializer.running); // pending removes itself after done - await sequentializer.setPending(1, Promise.resolve()); - assert.ok(!sequentializer.hasPending()); - assert.ok(!sequentializer.hasPending(1)); - assert.ok(!sequentializer.pending); - assert.ok(!sequentializer.hasNext()); + await sequentializer.run(1, Promise.resolve()); + assert.ok(!sequentializer.isRunning()); + assert.ok(!sequentializer.isRunning(1)); + assert.ok(!sequentializer.running); + assert.ok(!sequentializer.hasQueued()); // pending removes itself after done (use async.timeout) - sequentializer.setPending(2, async.timeout(1)); - assert.ok(sequentializer.hasPending()); - assert.ok(sequentializer.hasPending(2)); - assert.ok(!sequentializer.hasNext()); - assert.strictEqual(sequentializer.hasPending(1), false); - assert.ok(sequentializer.pending); + sequentializer.run(2, async.timeout(1)); + assert.ok(sequentializer.isRunning()); + assert.ok(sequentializer.isRunning(2)); + assert.ok(!sequentializer.hasQueued()); + assert.strictEqual(sequentializer.isRunning(1), false); + assert.ok(sequentializer.running); await async.timeout(2); - assert.strictEqual(sequentializer.hasPending(), false); - assert.strictEqual(sequentializer.hasPending(2), false); - assert.ok(!sequentializer.pending); + assert.strictEqual(sequentializer.isRunning(), false); + assert.strictEqual(sequentializer.isRunning(2), false); + assert.ok(!sequentializer.running); }); - test('pending and next (finishes instantly)', async function () { + test('executing and queued (finishes instantly)', async function () { const sequentializer = new async.TaskSequentializer(); let pendingDone = false; - sequentializer.setPending(1, async.timeout(1).then(() => { pendingDone = true; return; })); + sequentializer.run(1, async.timeout(1).then(() => { pendingDone = true; return; })); - // next finishes instantly - let nextDone = false; - const res = sequentializer.setNext(() => Promise.resolve(null).then(() => { nextDone = true; return; })); + // queued finishes instantly + let queuedDone = false; + const res = sequentializer.queue(() => Promise.resolve(null).then(() => { queuedDone = true; return; })); - assert.ok(sequentializer.hasNext()); + assert.ok(sequentializer.hasQueued()); await res; assert.ok(pendingDone); - assert.ok(nextDone); - assert.ok(!sequentializer.hasNext()); + assert.ok(queuedDone); + assert.ok(!sequentializer.hasQueued()); }); - test('pending and next (finishes after timeout)', async function () { + test('executing and queued (finishes after timeout)', async function () { const sequentializer = new async.TaskSequentializer(); let pendingDone = false; - sequentializer.setPending(1, async.timeout(1).then(() => { pendingDone = true; return; })); + sequentializer.run(1, async.timeout(1).then(() => { pendingDone = true; return; })); - // next finishes after async.timeout - let nextDone = false; - const res = sequentializer.setNext(() => async.timeout(1).then(() => { nextDone = true; return; })); + // queued finishes after async.timeout + let queuedDone = false; + const res = sequentializer.queue(() => async.timeout(1).then(() => { queuedDone = true; return; })); await res; assert.ok(pendingDone); - assert.ok(nextDone); - assert.ok(!sequentializer.hasNext()); + assert.ok(queuedDone); + assert.ok(!sequentializer.hasQueued()); }); - test('join (without next or pending)', async function () { + test('join (without executing or queued)', async function () { const sequentializer = new async.TaskSequentializer(); await sequentializer.join(); - assert.ok(!sequentializer.hasNext()); + assert.ok(!sequentializer.hasQueued()); }); - test('join (without next)', async function () { + test('join (without queued)', async function () { const sequentializer = new async.TaskSequentializer(); let pendingDone = false; - sequentializer.setPending(1, async.timeout(1).then(() => { pendingDone = true; return; })); + sequentializer.run(1, async.timeout(1).then(() => { pendingDone = true; return; })); await sequentializer.join(); assert.ok(pendingDone); - assert.ok(!sequentializer.hasPending()); + assert.ok(!sequentializer.isRunning()); }); - test('join (with next and pending)', async function () { + test('join (with executing and queued)', async function () { const sequentializer = new async.TaskSequentializer(); let pendingDone = false; - sequentializer.setPending(1, async.timeout(1).then(() => { pendingDone = true; return; })); + sequentializer.run(1, async.timeout(1).then(() => { pendingDone = true; return; })); - // next finishes after async.timeout - let nextDone = false; - sequentializer.setNext(() => async.timeout(1).then(() => { nextDone = true; return; })); + // queued finishes after async.timeout + let queuedDone = false; + sequentializer.queue(() => async.timeout(1).then(() => { queuedDone = true; return; })); await sequentializer.join(); assert.ok(pendingDone); - assert.ok(nextDone); - assert.ok(!sequentializer.hasPending()); - assert.ok(!sequentializer.hasNext()); + assert.ok(queuedDone); + assert.ok(!sequentializer.isRunning()); + assert.ok(!sequentializer.hasQueued()); }); - test('pending and multiple next (last one wins)', async function () { + test('executing and multiple queued (last one wins)', async function () { const sequentializer = new async.TaskSequentializer(); let pendingDone = false; - sequentializer.setPending(1, async.timeout(1).then(() => { pendingDone = true; return; })); + sequentializer.run(1, async.timeout(1).then(() => { pendingDone = true; return; })); - // next finishes after async.timeout + // queued finishes after async.timeout let firstDone = false; - const firstRes = sequentializer.setNext(() => async.timeout(2).then(() => { firstDone = true; return; })); + const firstRes = sequentializer.queue(() => async.timeout(2).then(() => { firstDone = true; return; })); let secondDone = false; - const secondRes = sequentializer.setNext(() => async.timeout(3).then(() => { secondDone = true; return; })); + const secondRes = sequentializer.queue(() => async.timeout(3).then(() => { secondDone = true; return; })); let thirdDone = false; - const thirdRes = sequentializer.setNext(() => async.timeout(4).then(() => { thirdDone = true; return; })); + const thirdRes = sequentializer.queue(() => async.timeout(4).then(() => { thirdDone = true; return; })); await Promise.all([firstRes, secondRes, thirdRes]); assert.ok(pendingDone); @@ -785,12 +785,12 @@ suite('Async', () => { assert.ok(thirdDone); }); - test('cancel pending', async function () { + test('cancel executing', async function () { const sequentializer = new async.TaskSequentializer(); let pendingCancelled = false; - sequentializer.setPending(1, async.timeout(1), () => pendingCancelled = true); - sequentializer.cancelPending(); + sequentializer.run(1, async.timeout(1), () => pendingCancelled = true); + sequentializer.cancelRunning(); assert.ok(pendingCancelled); }); @@ -1281,4 +1281,42 @@ suite('Async', () => { assert.strictEqual(worked, false); }); }); + + suite('LimitedQueue', () => { + + test('basics (with long running task)', async () => { + const limitedQueue = new async.LimitedQueue(); + + let counter = 0; + const promises = []; + for (let i = 0; i < 5; i++) { + promises.push(limitedQueue.queue(async () => { + counter = i; + await async.timeout(1); + })); + } + + await Promise.all(promises); + + // only the last task executed + assert.strictEqual(counter, 4); + }); + + test('basics (with sync running task)', async () => { + const limitedQueue = new async.LimitedQueue(); + + let counter = 0; + const promises = []; + for (let i = 0; i < 5; i++) { + promises.push(limitedQueue.queue(async () => { + counter = i; + })); + } + + await Promise.all(promises); + + // only the last task executed + assert.strictEqual(counter, 4); + }); + }); }); diff --git a/src/vs/code/node/sharedProcess/contrib/voiceTranscriber.ts b/src/vs/code/node/sharedProcess/contrib/voiceTranscriber.ts index 210570ef952..11299d0848e 100644 --- a/src/vs/code/node/sharedProcess/contrib/voiceTranscriber.ts +++ b/src/vs/code/node/sharedProcess/contrib/voiceTranscriber.ts @@ -9,7 +9,7 @@ import { Disposable, toDisposable } from 'vs/base/common/lifecycle'; import { IVoiceRecognitionService } from 'vs/platform/voiceRecognition/node/voiceRecognitionService'; import { ILogService } from 'vs/platform/log/common/log'; import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation'; -import { TaskSequentializer } from 'vs/base/common/async'; +import { LimitedQueue } from 'vs/base/common/async'; export class VoiceTranscriptionManager extends Disposable { @@ -34,9 +34,7 @@ class VoiceTranscriber extends Disposable { private static MAX_DATA_LENGTH = 30 /* seconds */ * 16000 /* sampling rate */ * 16 /* bith depth */ * 1 /* channels */ / 8; - private readonly transcriptionSequentializer = new TaskSequentializer(); - - private requests = 0; + private readonly transcriptionQueue = new LimitedQueue(); private data: Float32Array | undefined = undefined; @@ -67,7 +65,6 @@ class VoiceTranscriber extends Disposable { this.logService.info(`[voice] transcriber: closed connection`); cts.dispose(true); - this.transcriptionSequentializer.cancelPending(); }); } @@ -91,23 +88,21 @@ class VoiceTranscriber extends Disposable { } this.data = dataCandidate; - const data = this.data.slice(0); - this.requests++; - - if (!this.transcriptionSequentializer.hasPending()) { - this.transcriptionSequentializer.setPending(this.requests, this.transcribe(data, cancellation)); - } else { - this.transcriptionSequentializer.setNext(() => this.transcribe(data, cancellation)); - } + this.transcriptionQueue.queue(() => this.transcribe(cancellation)); } - private async transcribe(channelData: Float32Array, cancellation: CancellationToken): Promise { + private async transcribe(cancellation: CancellationToken): Promise { if (cancellation.isCancellationRequested) { return; } - const result = await this.voiceRecognitionService.transcribe(channelData, cancellation); + const data = this.data?.slice(0); + if (!data) { + return; + } + + const result = await this.voiceRecognitionService.transcribe(data, cancellation); if (cancellation.isCancellationRequested) { return; diff --git a/src/vs/workbench/services/textfile/common/textFileEditorModel.ts b/src/vs/workbench/services/textfile/common/textFileEditorModel.ts index 51af0329394..a60dc9a4560 100644 --- a/src/vs/workbench/services/textfile/common/textFileEditorModel.ts +++ b/src/vs/workbench/services/textfile/common/textFileEditorModel.ts @@ -290,7 +290,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil // Unless there are explicit contents provided, it is important that we do not // resolve a model that is dirty or is in the process of saving to prevent data // loss. - if (!options?.contents && (this.dirty || this.saveSequentializer.hasPending())) { + if (!options?.contents && (this.dirty || this.saveSequentializer.isRunning())) { this.trace('resolve() - exit - without resolving because model is dirty or being saved'); return; @@ -767,15 +767,15 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil return; } - // Lookup any running pending save for this versionId and return it if found + // Lookup any running save for this versionId and return it if found // // Scenario: user invoked the save action multiple times quickly for the same contents // while the save was not yet finished to disk // - if (this.saveSequentializer.hasPending(versionId)) { - this.trace(`doSave(${versionId}) - exit - found a pending save for versionId ${versionId}`); + if (this.saveSequentializer.isRunning(versionId)) { + this.trace(`doSave(${versionId}) - exit - found a running save for versionId ${versionId}`); - return this.saveSequentializer.pending; + return this.saveSequentializer.running; } // Return early if not dirty (unless forced) @@ -795,18 +795,18 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil // Scenario B: save is very slow (e.g. network share) and the user manages to change the buffer and trigger another save // while the first save has not returned yet. // - if (this.saveSequentializer.hasPending()) { + if (this.saveSequentializer.isRunning()) { this.trace(`doSave(${versionId}) - exit - because busy saving`); // Indicate to the save sequentializer that we want to - // cancel the pending operation so that ours can run - // before the pending one finishes. - // Currently this will try to cancel pending save - // participants but never a pending save. - this.saveSequentializer.cancelPending(); + // cancel the running operation so that ours can run + // before the running one finishes. + // Currently this will try to cancel running save + // participants but never a running save. + this.saveSequentializer.cancelRunning(); - // Register this as the next upcoming save and return - return this.saveSequentializer.setNext(() => this.doSave(options)); + // Queue this as the upcoming save and return + return this.saveSequentializer.queue(() => this.doSave(options)); } // Push all edit operations to the undo stack so that the user has a chance to @@ -817,7 +817,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil const saveCancellation = new CancellationTokenSource(); - return this.saveSequentializer.setPending(versionId, (async () => { + return this.saveSequentializer.run(versionId, (async () => { // A save participant can still change the model now and since we are so close to saving // we do not want to trigger another auto save or similar, so we block this @@ -894,13 +894,13 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil // Clear error flag since we are trying to save again this.inErrorMode = false; - // Save to Disk. We mark the save operation as currently pending with + // Save to Disk. We mark the save operation as currently running with // the latest versionId because it might have changed from a save // participant triggering this.trace(`doSave(${versionId}) - before write()`); const lastResolvedFileStat = assertIsDefined(this.lastResolvedFileStat); const resolvedTextFileEditorModel = this; - return this.saveSequentializer.setPending(versionId, (async () => { + return this.saveSequentializer.run(versionId, (async () => { try { const stat = await this.textFileService.write(lastResolvedFileStat.resource, resolvedTextFileEditorModel.createSnapshot(), { mtime: lastResolvedFileStat.mtime, @@ -1013,14 +1013,14 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil case TextFileEditorModelState.ORPHAN: return this.inOrphanMode; case TextFileEditorModelState.PENDING_SAVE: - return this.saveSequentializer.hasPending(); + return this.saveSequentializer.isRunning(); case TextFileEditorModelState.SAVED: return !this.dirty; } } async joinState(state: TextFileEditorModelState.PENDING_SAVE): Promise { - return this.saveSequentializer.pending; + return this.saveSequentializer.running; } override getLanguageId(this: IResolvedTextFileEditorModel): string; diff --git a/src/vs/workbench/services/workingCopy/common/storedFileWorkingCopy.ts b/src/vs/workbench/services/workingCopy/common/storedFileWorkingCopy.ts index d3fff96bb86..f96b3de0015 100644 --- a/src/vs/workbench/services/workingCopy/common/storedFileWorkingCopy.ts +++ b/src/vs/workbench/services/workingCopy/common/storedFileWorkingCopy.ts @@ -433,7 +433,7 @@ export class StoredFileWorkingCopy extend // Unless there are explicit contents provided, it is important that we do not // resolve a working copy that is dirty or is in the process of saving to prevent // data loss. - if (!options?.contents && (this.dirty || this.saveSequentializer.hasPending())) { + if (!options?.contents && (this.dirty || this.saveSequentializer.isRunning())) { this.trace('resolve() - exit - without resolving because file working copy is dirty or being saved'); return; @@ -851,15 +851,15 @@ export class StoredFileWorkingCopy extend return; } - // Lookup any running pending save for this versionId and return it if found + // Lookup any running save for this versionId and return it if found // // Scenario: user invoked the save action multiple times quickly for the same contents // while the save was not yet finished to disk // - if (this.saveSequentializer.hasPending(versionId)) { - this.trace(`doSave(${versionId}) - exit - found a pending save for versionId ${versionId}`); + if (this.saveSequentializer.isRunning(versionId)) { + this.trace(`doSave(${versionId}) - exit - found a running save for versionId ${versionId}`); - return this.saveSequentializer.pending; + return this.saveSequentializer.running; } // Return early if not dirty (unless forced) @@ -879,20 +879,20 @@ export class StoredFileWorkingCopy extend // Scenario B: save is very slow (e.g. network share) and the user manages to change the working copy and trigger another save // while the first save has not returned yet. // - if (this.saveSequentializer.hasPending()) { + if (this.saveSequentializer.isRunning()) { this.trace(`doSave(${versionId}) - exit - because busy saving`); // Indicate to the save sequentializer that we want to - // cancel the pending operation so that ours can run - // before the pending one finishes. - // Currently this will try to cancel pending save - // participants and pending snapshots from the + // cancel the running operation so that ours can run + // before the running one finishes. + // Currently this will try to cancel running save + // participants and running snapshots from the // save operation, but not the actual save which does // not support cancellation yet. - this.saveSequentializer.cancelPending(); + this.saveSequentializer.cancelRunning(); - // Register this as the next upcoming save and return - return this.saveSequentializer.setNext(() => this.doSave(options)); + // Queue this as the upcoming save and return + return this.saveSequentializer.queue(() => this.doSave(options)); } // Push all edit operations to the undo stack so that the user has a chance to @@ -903,7 +903,7 @@ export class StoredFileWorkingCopy extend const saveCancellation = new CancellationTokenSource(); - return this.saveSequentializer.setPending(versionId, (async () => { + return this.saveSequentializer.run(versionId, (async () => { // A save participant can still change the working copy now // and since we are so close to saving we do not want to trigger @@ -975,13 +975,13 @@ export class StoredFileWorkingCopy extend // Clear error flag since we are trying to save again this.inErrorMode = false; - // Save to Disk. We mark the save operation as currently pending with + // Save to Disk. We mark the save operation as currently running with // the latest versionId because it might have changed from a save // participant triggering this.trace(`doSave(${versionId}) - before write()`); const lastResolvedFileStat = assertIsDefined(this.lastResolvedFileStat); const resolvedFileWorkingCopy = this; - return this.saveSequentializer.setPending(versionId, (async () => { + return this.saveSequentializer.run(versionId, (async () => { try { const writeFileOptions: IWriteFileOptions = { mtime: lastResolvedFileStat.mtime, @@ -1256,14 +1256,14 @@ export class StoredFileWorkingCopy extend case StoredFileWorkingCopyState.ORPHAN: return this.isOrphaned(); case StoredFileWorkingCopyState.PENDING_SAVE: - return this.saveSequentializer.hasPending(); + return this.saveSequentializer.isRunning(); case StoredFileWorkingCopyState.SAVED: return !this.dirty; } } async joinState(state: StoredFileWorkingCopyState.PENDING_SAVE): Promise { - return this.saveSequentializer.pending; + return this.saveSequentializer.running; } //#endregion From 6b74d08f5b021abbaeaed7113bae3d5aaea6081e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Fri, 25 Aug 2023 15:14:07 +0200 Subject: [PATCH 221/221] :lipstick: (#191313) cc @rzhao271 --- build/azure-pipelines/common/sign.js | 2 +- build/azure-pipelines/common/sign.ts | 2 +- build/azure-pipelines/linux/product-build-linux.yml | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/azure-pipelines/common/sign.js b/build/azure-pipelines/common/sign.js index fc522d4ef60..993711adfbf 100644 --- a/build/azure-pipelines/common/sign.js +++ b/build/azure-pipelines/common/sign.js @@ -34,7 +34,7 @@ function getParams(type) { return '[{"keyCode":"CP-230012","operationSetCode":"SigntoolSign","parameters":[{"parameterName":"OpusName","parameterValue":"VS Code"},{"parameterName":"OpusInfo","parameterValue":"https://code.visualstudio.com/"},{"parameterName":"Append","parameterValue":"/as"},{"parameterName":"FileDigest","parameterValue":"/fd \\"SHA256\\""},{"parameterName":"PageHash","parameterValue":"/NPH"},{"parameterName":"TimeStamp","parameterValue":"/tr \\"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\\" /td sha256"}],"toolName":"sign","toolVersion":"1.0"},{"keyCode":"CP-230012","operationSetCode":"SigntoolVerify","parameters":[{"parameterName":"VerifyAll","parameterValue":"/all"}],"toolName":"sign","toolVersion":"1.0"}]'; case 'windows-appx': return '[{"keyCode":"CP-229979","operationSetCode":"SigntoolSign","parameters":[{"parameterName":"OpusName","parameterValue":"VS Code"},{"parameterName":"OpusInfo","parameterValue":"https://code.visualstudio.com/"},{"parameterName":"FileDigest","parameterValue":"/fd \\"SHA256\\""},{"parameterName":"PageHash","parameterValue":"/NPH"},{"parameterName":"TimeStamp","parameterValue":"/tr \\"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\\" /td sha256"}],"toolName":"sign","toolVersion":"1.0"},{"keyCode":"CP-229979","operationSetCode":"SigntoolVerify","parameters":[],"toolName":"sign","toolVersion":"1.0"}]'; - case 'rpm': + case 'pgp': return '[{ "keyCode": "CP-450779-Pgp", "operationSetCode": "LinuxSign", "parameters": [], "toolName": "sign", "toolVersion": "1.0" }]'; case 'darwin-sign': return '[{"keyCode":"CP-401337-Apple","operationSetCode":"MacAppDeveloperSign","parameters":[{"parameterName":"Hardening","parameterValue":"--options=runtime"}],"toolName":"sign","toolVersion":"1.0"}]'; diff --git a/build/azure-pipelines/common/sign.ts b/build/azure-pipelines/common/sign.ts index 955c9389c02..494e89b3e12 100644 --- a/build/azure-pipelines/common/sign.ts +++ b/build/azure-pipelines/common/sign.ts @@ -35,7 +35,7 @@ function getParams(type: string): string { return '[{"keyCode":"CP-230012","operationSetCode":"SigntoolSign","parameters":[{"parameterName":"OpusName","parameterValue":"VS Code"},{"parameterName":"OpusInfo","parameterValue":"https://code.visualstudio.com/"},{"parameterName":"Append","parameterValue":"/as"},{"parameterName":"FileDigest","parameterValue":"/fd \\"SHA256\\""},{"parameterName":"PageHash","parameterValue":"/NPH"},{"parameterName":"TimeStamp","parameterValue":"/tr \\"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\\" /td sha256"}],"toolName":"sign","toolVersion":"1.0"},{"keyCode":"CP-230012","operationSetCode":"SigntoolVerify","parameters":[{"parameterName":"VerifyAll","parameterValue":"/all"}],"toolName":"sign","toolVersion":"1.0"}]'; case 'windows-appx': return '[{"keyCode":"CP-229979","operationSetCode":"SigntoolSign","parameters":[{"parameterName":"OpusName","parameterValue":"VS Code"},{"parameterName":"OpusInfo","parameterValue":"https://code.visualstudio.com/"},{"parameterName":"FileDigest","parameterValue":"/fd \\"SHA256\\""},{"parameterName":"PageHash","parameterValue":"/NPH"},{"parameterName":"TimeStamp","parameterValue":"/tr \\"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\\" /td sha256"}],"toolName":"sign","toolVersion":"1.0"},{"keyCode":"CP-229979","operationSetCode":"SigntoolVerify","parameters":[],"toolName":"sign","toolVersion":"1.0"}]'; - case 'rpm': + case 'pgp': return '[{ "keyCode": "CP-450779-Pgp", "operationSetCode": "LinuxSign", "parameters": [], "toolName": "sign", "toolVersion": "1.0" }]'; case 'darwin-sign': return '[{"keyCode":"CP-401337-Apple","operationSetCode":"MacAppDeveloperSign","parameters":[{"parameterName":"Hardening","parameterValue":"--options=runtime"}],"toolName":"sign","toolVersion":"1.0"}]'; diff --git a/build/azure-pipelines/linux/product-build-linux.yml b/build/azure-pipelines/linux/product-build-linux.yml index 4641edf7670..919d48eac37 100644 --- a/build/azure-pipelines/linux/product-build-linux.yml +++ b/build/azure-pipelines/linux/product-build-linux.yml @@ -312,10 +312,10 @@ steps: continueOnError: true displayName: Download ESRPClient - - script: node build/azure-pipelines/common/sign $(Agent.ToolsDirectory)/esrpclient/*/*/net6.0/esrpcli.dll rpm $(ESRP-PKI) $(esrp-aad-username) $(esrp-aad-password) .build/linux/deb '*.deb' + - script: node build/azure-pipelines/common/sign $(Agent.ToolsDirectory)/esrpclient/*/*/net6.0/esrpcli.dll pgp $(ESRP-PKI) $(esrp-aad-username) $(esrp-aad-password) .build/linux/deb '*.deb' displayName: Codesign deb - - script: node build/azure-pipelines/common/sign $(Agent.ToolsDirectory)/esrpclient/*/*/net6.0/esrpcli.dll rpm $(ESRP-PKI) $(esrp-aad-username) $(esrp-aad-password) .build/linux/rpm '*.rpm' + - script: node build/azure-pipelines/common/sign $(Agent.ToolsDirectory)/esrpclient/*/*/net6.0/esrpcli.dll pgp $(ESRP-PKI) $(esrp-aad-username) $(esrp-aad-password) .build/linux/rpm '*.rpm' displayName: Codesign rpm - script: echo "##vso[task.setvariable variable=ARTIFACT_PREFIX]attempt$(System.JobAttempt)_"