From a76c242e3de4e11d5d3e11116c6fe22801adb8f0 Mon Sep 17 00:00:00 2001 From: BeniBenj Date: Thu, 25 Apr 2024 15:26:42 +0200 Subject: [PATCH 001/104] Update shouldShowCustomTitleBar function to consider zenModeActive parameter --- src/vs/workbench/browser/layout.ts | 35 +++++++++++-------- .../parts/editor/auxiliaryEditorPart.ts | 4 +-- .../services/layout/browser/layoutService.ts | 6 +++- 3 files changed, 28 insertions(+), 17 deletions(-) diff --git a/src/vs/workbench/browser/layout.ts b/src/vs/workbench/browser/layout.ts index 94ec1087453c1..eb99b820cb02f 100644 --- a/src/vs/workbench/browser/layout.ts +++ b/src/vs/workbench/browser/layout.ts @@ -427,12 +427,12 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi // The menu bar toggles the title bar in web because it does not need to be shown for window controls only if (isWeb && menuBarVisibility === 'toggle') { - this.workbenchGrid.setViewVisible(this.titleBarPartView, shouldShowCustomTitleBar(this.configurationService, mainWindow, this.state.runtime.menuBar.toggled)); + this.workbenchGrid.setViewVisible(this.titleBarPartView, shouldShowCustomTitleBar(this.configurationService, mainWindow, this.state.runtime.menuBar.toggled, this.isZenModeActive())); } // The menu bar toggles the title bar in full screen for toggle and classic settings else if (this.state.runtime.mainWindowFullscreen && (menuBarVisibility === 'toggle' || menuBarVisibility === 'classic')) { - this.workbenchGrid.setViewVisible(this.titleBarPartView, shouldShowCustomTitleBar(this.configurationService, mainWindow, this.state.runtime.menuBar.toggled)); + this.workbenchGrid.setViewVisible(this.titleBarPartView, shouldShowCustomTitleBar(this.configurationService, mainWindow, this.state.runtime.menuBar.toggled, this.isZenModeActive())); } // Move layout call to any time the menubar @@ -468,8 +468,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi this.mainContainer.classList.remove(LayoutClasses.FULLSCREEN); const zenModeExitInfo = this.stateModel.getRuntimeValue(LayoutStateKeys.ZEN_MODE_EXIT_INFO); - const zenModeActive = this.stateModel.getRuntimeValue(LayoutStateKeys.ZEN_MODE_ACTIVE); - if (zenModeExitInfo.transitionedToFullScreen && zenModeActive) { + if (zenModeExitInfo.transitionedToFullScreen && this.isZenModeActive()) { this.toggleZenMode(); } } @@ -482,7 +481,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi if (hasCustomTitlebar(this.configurationService)) { // Propagate to grid - this.workbenchGrid.setViewVisible(this.titleBarPartView, shouldShowCustomTitleBar(this.configurationService, mainWindow, this.state.runtime.menuBar.toggled)); + this.workbenchGrid.setViewVisible(this.titleBarPartView, shouldShowCustomTitleBar(this.configurationService, mainWindow, this.state.runtime.menuBar.toggled, this.isZenModeActive())); this.updateWindowsBorder(true); } @@ -1072,11 +1071,11 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi })()); // Restore Zen Mode - const zenModeWasActive = this.stateModel.getRuntimeValue(LayoutStateKeys.ZEN_MODE_ACTIVE); + const zenModeWasActive = this.isZenModeActive(); const restoreZenMode = getZenModeConfiguration(this.configurationService).restore; if (zenModeWasActive) { - this.stateModel.setRuntimeValue(LayoutStateKeys.ZEN_MODE_ACTIVE, !restoreZenMode); + this.setZenModeActive(!restoreZenMode); this.toggleZenMode(false, true); } @@ -1221,7 +1220,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi switch (part) { case Parts.TITLEBAR_PART: - return shouldShowCustomTitleBar(this.configurationService, mainWindow, this.state.runtime.menuBar.toggled); + return shouldShowCustomTitleBar(this.configurationService, mainWindow, this.state.runtime.menuBar.toggled, this.isZenModeActive()); case Parts.SIDEBAR_PART: return !this.stateModel.getRuntimeValue(LayoutStateKeys.SIDEBAR_HIDDEN); case Parts.PANEL_PART: @@ -1287,8 +1286,16 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi } } + private isZenModeActive(): boolean { + return this.stateModel.getRuntimeValue(LayoutStateKeys.ZEN_MODE_ACTIVE); + } + + private setZenModeActive(active: boolean) { + this.stateModel.setRuntimeValue(LayoutStateKeys.ZEN_MODE_ACTIVE, active); + } + toggleZenMode(skipLayout?: boolean, restoring = false): void { - this.stateModel.setRuntimeValue(LayoutStateKeys.ZEN_MODE_ACTIVE, !this.stateModel.getRuntimeValue(LayoutStateKeys.ZEN_MODE_ACTIVE)); + this.setZenModeActive(!this.isZenModeActive()); this.state.runtime.zenMode.transitionDisposables.clearAndDisposeAll(); const setLineNumbers = (lineNumbers?: LineNumbersType) => { @@ -1314,7 +1321,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi const zenModeExitInfo = this.stateModel.getRuntimeValue(LayoutStateKeys.ZEN_MODE_EXIT_INFO); // Zen Mode Active - if (this.stateModel.getRuntimeValue(LayoutStateKeys.ZEN_MODE_ACTIVE)) { + if (this.isZenModeActive()) { toggleMainWindowFullScreen = !this.state.runtime.mainWindowFullscreen && config.fullScreen && !isIOS; @@ -1446,7 +1453,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi } // Event - this._onDidChangeZenMode.fire(this.stateModel.getRuntimeValue(LayoutStateKeys.ZEN_MODE_ACTIVE)); + this._onDidChangeZenMode.fire(this.isZenModeActive()); } private setStatusBarHidden(hidden: boolean, skipLayout?: boolean): void { @@ -2024,14 +2031,14 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi } updateMenubarVisibility(skipLayout: boolean): void { - const shouldShowTitleBar = shouldShowCustomTitleBar(this.configurationService, mainWindow, this.state.runtime.menuBar.toggled); + const shouldShowTitleBar = shouldShowCustomTitleBar(this.configurationService, mainWindow, this.state.runtime.menuBar.toggled, this.isZenModeActive()); if (!skipLayout && this.workbenchGrid && shouldShowTitleBar !== this.isVisible(Parts.TITLEBAR_PART, mainWindow)) { this.workbenchGrid.setViewVisible(this.titleBarPartView, shouldShowTitleBar); } } updateCustomTitleBarVisibility(): void { - const shouldShowTitleBar = shouldShowCustomTitleBar(this.configurationService, mainWindow, this.state.runtime.menuBar.toggled); + const shouldShowTitleBar = shouldShowCustomTitleBar(this.configurationService, mainWindow, this.state.runtime.menuBar.toggled, this.isZenModeActive()); const titlebarVisible = this.isVisible(Parts.TITLEBAR_PART); if (shouldShowTitleBar !== titlebarVisible) { this.workbenchGrid.setViewVisible(this.titleBarPartView, shouldShowTitleBar); @@ -2189,7 +2196,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi this.workbenchGrid.moveView(this.bannerPartView, Sizing.Distribute, this.titleBarPartView, shouldBannerBeFirst ? Direction.Up : Direction.Down); } - this.workbenchGrid.setViewVisible(this.titleBarPartView, shouldShowCustomTitleBar(this.configurationService, mainWindow, this.state.runtime.menuBar.toggled)); + this.workbenchGrid.setViewVisible(this.titleBarPartView, shouldShowCustomTitleBar(this.configurationService, mainWindow, this.state.runtime.menuBar.toggled, this.isZenModeActive())); } private arrangeEditorNodes(nodes: { editor: ISerializedNode; sideBar?: ISerializedNode; auxiliaryBar?: ISerializedNode }, availableHeight: number, availableWidth: number): ISerializedNode { diff --git a/src/vs/workbench/browser/parts/editor/auxiliaryEditorPart.ts b/src/vs/workbench/browser/parts/editor/auxiliaryEditorPart.ts index a3062e62d472c..f0341568cf00f 100644 --- a/src/vs/workbench/browser/parts/editor/auxiliaryEditorPart.ts +++ b/src/vs/workbench/browser/parts/editor/auxiliaryEditorPart.ts @@ -121,11 +121,11 @@ export class AuxiliaryEditorPart { const useCustomTitle = isNative && hasCustomTitlebar(this.configurationService); // custom title in aux windows only enabled in native if (useCustomTitle) { titlebarPart = disposables.add(this.titleService.createAuxiliaryTitlebarPart(auxiliaryWindow.container, editorPart)); - titlebarVisible = shouldShowCustomTitleBar(this.configurationService, auxiliaryWindow.window); + titlebarVisible = shouldShowCustomTitleBar(this.configurationService, auxiliaryWindow.window, undefined, false); const handleTitleBarVisibilityEvent = () => { const oldTitlebarPartVisible = titlebarVisible; - titlebarVisible = shouldShowCustomTitleBar(this.configurationService, auxiliaryWindow.window); + titlebarVisible = shouldShowCustomTitleBar(this.configurationService, auxiliaryWindow.window, undefined, false); if (oldTitlebarPartVisible !== titlebarVisible) { updateTitlebarVisibility(true); } diff --git a/src/vs/workbench/services/layout/browser/layoutService.ts b/src/vs/workbench/services/layout/browser/layoutService.ts index 769664b057427..3357adabc8228 100644 --- a/src/vs/workbench/services/layout/browser/layoutService.ts +++ b/src/vs/workbench/services/layout/browser/layoutService.ts @@ -311,12 +311,16 @@ export interface IWorkbenchLayoutService extends ILayoutService { getVisibleNeighborPart(part: Parts, direction: Direction): Parts | undefined; } -export function shouldShowCustomTitleBar(configurationService: IConfigurationService, window: Window, menuBarToggled?: boolean): boolean { +export function shouldShowCustomTitleBar(configurationService: IConfigurationService, window: Window, menuBarToggled?: boolean, zenModeActive?: boolean): boolean { if (!hasCustomTitlebar(configurationService)) { return false; } + if (zenModeActive) { + return false; + } + const inFullscreen = isFullscreen(window); const nativeTitleBarEnabled = hasNativeTitlebar(configurationService); From 3415990696a2d269e7f4556369d44ed5b71dfabf Mon Sep 17 00:00:00 2001 From: Logan Ramos Date: Thu, 25 Apr 2024 12:12:54 -0700 Subject: [PATCH 002/104] Add verification steps needed to endgame notebook (#211385) --- .vscode/notebooks/endgame.github-issues | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.vscode/notebooks/endgame.github-issues b/.vscode/notebooks/endgame.github-issues index 7b179b322bf46..4fb94c29edda6 100644 --- a/.vscode/notebooks/endgame.github-issues +++ b/.vscode/notebooks/endgame.github-issues @@ -114,6 +114,16 @@ "language": "github-issues", "value": "$REPOS $MILESTONE is:issue is:closed reason:completed sort:updated-asc label:bug -label:verified -label:on-testplan -label:*duplicate -label:duplicate -label:invalid -label:*as-designed -label:error-telemetry -label:verification-steps-needed -label:z-author-verified -label:unreleased -label:*not-reproducible" }, + { + "kind": 1, + "language": "markdown", + "value": "## Verifiable Fixes Missing Steps" + }, + { + "kind": 2, + "language": "github-issues", + "value": "$REPOS $MILESTONE is:issue is:closed reason:completed sort:updated-asc label:bug label:verification-steps-needed -label:verified -label:on-testplan -label:*duplicate -label:duplicate -label:invalid -label:*as-designed -label:error-telemetry -label:z-author-verified -label:unreleased -label:*not-reproducible" + }, { "kind": 1, "language": "markdown", From 56ad6311c84815e9014663a49b176522cac81b23 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Thu, 25 Apr 2024 13:48:44 -0700 Subject: [PATCH 003/104] Pick up latest Markdown language service (#211391) Fixes #211389 --- .../markdown-language-features/server/package.json | 4 ++-- .../server/src/protocol.ts | 2 +- .../markdown-language-features/server/src/server.ts | 8 +++++++- .../markdown-language-features/server/yarn.lock | 8 ++++---- .../markdown-language-features/src/client/client.ts | 13 +++++++++---- .../src/client/protocol.ts | 2 +- .../src/markdownEngine.ts | 2 +- 7 files changed, 25 insertions(+), 14 deletions(-) diff --git a/extensions/markdown-language-features/server/package.json b/extensions/markdown-language-features/server/package.json index 866e1a796e158..df9124c936b9b 100644 --- a/extensions/markdown-language-features/server/package.json +++ b/extensions/markdown-language-features/server/package.json @@ -1,7 +1,7 @@ { "name": "vscode-markdown-languageserver", "description": "Markdown language server", - "version": "0.5.0-alpha.5", + "version": "0.5.0-alpha.6", "author": "Microsoft Corporation", "license": "MIT", "engines": { @@ -18,7 +18,7 @@ "vscode-languageserver": "^8.1.0", "vscode-languageserver-textdocument": "^1.0.8", "vscode-languageserver-types": "^3.17.3", - "vscode-markdown-languageservice": "^0.5.0-alpha.5", + "vscode-markdown-languageservice": "^0.5.0-alpha.6", "vscode-uri": "^3.0.7" }, "devDependencies": { diff --git a/extensions/markdown-language-features/server/src/protocol.ts b/extensions/markdown-language-features/server/src/protocol.ts index 3a195755e056b..d06edbd4303ef 100644 --- a/extensions/markdown-language-features/server/src/protocol.ts +++ b/extensions/markdown-language-features/server/src/protocol.ts @@ -8,7 +8,7 @@ import type * as lsp from 'vscode-languageserver-types'; import type * as md from 'vscode-markdown-languageservice'; //#region From server -export const parse = new RequestType<{ uri: string }, md.Token[], any>('markdown/parse'); +export const parse = new RequestType<{ uri: string; text?: string }, md.Token[], any>('markdown/parse'); export const fs_readFile = new RequestType<{ uri: string }, number[], any>('markdown/fs/readFile'); export const fs_readDirectory = new RequestType<{ uri: string }, [string, { isDirectory: boolean }][], any>('markdown/fs/readDirectory'); diff --git a/extensions/markdown-language-features/server/src/server.ts b/extensions/markdown-language-features/server/src/server.ts index d0b17ab138187..f1df5494f3b7c 100644 --- a/extensions/markdown-language-features/server/src/server.ts +++ b/extensions/markdown-language-features/server/src/server.ts @@ -29,7 +29,13 @@ export async function startVsCodeServer(connection: Connection) { slugifier = md.githubSlugifier; tokenize(document: md.ITextDocument): Promise { - return connection.sendRequest(protocol.parse, { uri: document.uri.toString() }); + return connection.sendRequest(protocol.parse, { + uri: document.uri, + + // Clients won't be able to read temp documents. + // Send along the full text for parsing. + text: document.version < 0 ? document.getText() : undefined + }); } }; diff --git a/extensions/markdown-language-features/server/yarn.lock b/extensions/markdown-language-features/server/yarn.lock index 87a251842eaee..0768663fe0d50 100644 --- a/extensions/markdown-language-features/server/yarn.lock +++ b/extensions/markdown-language-features/server/yarn.lock @@ -151,10 +151,10 @@ vscode-languageserver@^8.1.0: dependencies: vscode-languageserver-protocol "3.17.3" -vscode-markdown-languageservice@^0.5.0-alpha.5: - version "0.5.0-alpha.5" - resolved "https://registry.yarnpkg.com/vscode-markdown-languageservice/-/vscode-markdown-languageservice-0.5.0-alpha.5.tgz#d4c5a4b7ab8d03a9dbbdf64ce51862686ca05cf8" - integrity sha512-yu2TbIj2alrgh7JAzGQS4YadSBX4MDT7UjgrT4BQvtGfXOPC4G76llP4iZpkDWPBvAXywxnMZ9eZ3N15f81InA== +vscode-markdown-languageservice@^0.5.0-alpha.6: + version "0.5.0-alpha.6" + resolved "https://registry.yarnpkg.com/vscode-markdown-languageservice/-/vscode-markdown-languageservice-0.5.0-alpha.6.tgz#3aa5fc94fea3d5d7f0cd970e64348e2791643dc0" + integrity sha512-mA1JCA7aHHSek5gr8Yv7C3esEPo2hRrgxmoZUDRro+pnwbdsJuRaWOKWtCWxejRUVVVhc/5yTK2X64Jx9OCmFQ== dependencies: "@vscode/l10n" "^0.0.10" node-html-parser "^6.1.5" diff --git a/extensions/markdown-language-features/src/client/client.ts b/extensions/markdown-language-features/src/client/client.ts index 5964b43c3774a..a2f7861550809 100644 --- a/extensions/markdown-language-features/src/client/client.ts +++ b/extensions/markdown-language-features/src/client/client.ts @@ -9,6 +9,7 @@ import { IMdParser } from '../markdownEngine'; import { IDisposable } from '../util/dispose'; import { looksLikeMarkdownPath, markdownFileExtensions } from '../util/file'; import { FileWatcherManager } from './fileWatchingManager'; +import { InMemoryDocument } from './inMemoryDocument'; import * as proto from './protocol'; import { VsCodeMdWorkspace } from './workspace'; @@ -101,11 +102,15 @@ export async function startClient(factory: LanguageClientConstructor, parser: IM client.onRequest(proto.parse, async (e) => { const uri = vscode.Uri.parse(e.uri); - const doc = await workspace.getOrLoadMarkdownDocument(uri); - if (doc) { - return parser.tokenize(doc); + if (typeof e.text === 'string') { + return parser.tokenize(new InMemoryDocument(uri, e.text, -1)); } else { - return []; + const doc = await workspace.getOrLoadMarkdownDocument(uri); + if (doc) { + return parser.tokenize(doc); + } else { + return []; + } } }); diff --git a/extensions/markdown-language-features/src/client/protocol.ts b/extensions/markdown-language-features/src/client/protocol.ts index 2f6c48b371d7c..69d162f8262f3 100644 --- a/extensions/markdown-language-features/src/client/protocol.ts +++ b/extensions/markdown-language-features/src/client/protocol.ts @@ -16,7 +16,7 @@ export type ResolvedDocumentLinkTarget = | { readonly kind: 'external'; readonly uri: vscode.Uri }; //#region From server -export const parse = new RequestType<{ uri: string }, Token[], any>('markdown/parse'); +export const parse = new RequestType<{ uri: string; text?: string }, Token[], any>('markdown/parse'); export const fs_readFile = new RequestType<{ uri: string }, number[], any>('markdown/fs/readFile'); export const fs_readDirectory = new RequestType<{ uri: string }, [string, { isDirectory: boolean }][], any>('markdown/fs/readDirectory'); diff --git a/extensions/markdown-language-features/src/markdownEngine.ts b/extensions/markdown-language-features/src/markdownEngine.ts index 0ef05452e4f89..103cbc191e419 100644 --- a/extensions/markdown-language-features/src/markdownEngine.ts +++ b/extensions/markdown-language-features/src/markdownEngine.ts @@ -55,7 +55,7 @@ class TokenCache { public tryGetCached(document: ITextDocument, config: MarkdownItConfig): Token[] | undefined { if (this._cachedDocument && this._cachedDocument.uri.toString() === document.uri.toString() - && this._cachedDocument.version === document.version + && document.version >= 0 && this._cachedDocument.version === document.version && this._cachedDocument.config.breaks === config.breaks && this._cachedDocument.config.linkify === config.linkify ) { From 8c7a3faae8fa2443eea7f06a12371b0a729fe7c4 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Thu, 28 Mar 2024 18:19:30 -0300 Subject: [PATCH 004/104] Add error message for chat loading --- .../contrib/chat/common/chatServiceImpl.ts | 19 +++++++++++++++++-- .../test/browser/inlineChatController.test.ts | 3 +++ .../test/browser/inlineChatSession.test.ts | 3 +++ 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/chat/common/chatServiceImpl.ts b/src/vs/workbench/contrib/chat/common/chatServiceImpl.ts index d2ac621f3b5a1..f937415cf67d3 100644 --- a/src/vs/workbench/contrib/chat/common/chatServiceImpl.ts +++ b/src/vs/workbench/contrib/chat/common/chatServiceImpl.ts @@ -3,6 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { Action } from 'vs/base/common/actions'; import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation'; import { ErrorNoTelemetry } from 'vs/base/common/errors'; import { Emitter, Event } from 'vs/base/common/event'; @@ -13,9 +14,10 @@ import { revive } from 'vs/base/common/marshalling'; import { StopWatch } from 'vs/base/common/stopwatch'; import { URI, UriComponents } from 'vs/base/common/uri'; import { localize } from 'vs/nls'; -import { CommandsRegistry } from 'vs/platform/commands/common/commands'; +import { CommandsRegistry, ICommandService } from 'vs/platform/commands/common/commands'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { ILogService } from 'vs/platform/log/common/log'; +import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; import { Progress } from 'vs/platform/progress/common/progress'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; @@ -145,7 +147,9 @@ export class ChatService extends Disposable implements IChatService { @IWorkspaceContextService private readonly workspaceContextService: IWorkspaceContextService, @IChatSlashCommandService private readonly chatSlashCommandService: IChatSlashCommandService, @IChatVariablesService private readonly chatVariablesService: IChatVariablesService, - @IChatAgentService private readonly chatAgentService: IChatAgentService + @IChatAgentService private readonly chatAgentService: IChatAgentService, + @INotificationService private readonly notificationService: INotificationService, + @ICommandService private readonly commandService: ICommandService, ) { super(); @@ -349,6 +353,17 @@ export class ChatService extends Disposable implements IChatService { const defaultAgent = this.chatAgentService.getActivatedAgents().find(agent => agent.id === defaultAgentData.id); if (!defaultAgent) { // Should have been registered during activation above! + this.notificationService.notify({ + severity: Severity.Error, + message: localize('chatFailErrorMessage', "Chat failed to load. Please ensure that the GitHub Copilot Chat extension is up to date."), + actions: { + primary: [ + new Action('showExtension', localize('action.showExtension', "Show Extension"), undefined, true, () => { + return this.commandService.executeCommand('workbench.extensions.action.showExtensionsWithIds', ['GitHub.copilot-chat']); + }) + ] + } + }); throw new ErrorNoTelemetry('No default agent registered'); } const welcomeMessage = model.welcomeMessage ? undefined : await defaultAgent.provideWelcomeMessage?.(model.initialLocation, token) ?? undefined; 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 057adbf762273..5bf79cc39715b 100644 --- a/src/vs/workbench/contrib/inlineChat/test/browser/inlineChatController.test.ts +++ b/src/vs/workbench/contrib/inlineChat/test/browser/inlineChatController.test.ts @@ -58,6 +58,8 @@ import { ChatWidgetHistoryService, IChatWidgetHistoryService } from 'vs/workbenc import { IHoverService } from 'vs/platform/hover/browser/hover'; import { NullHoverService } from 'vs/platform/hover/test/browser/nullHoverService'; import { ChatVariablesService } from 'vs/workbench/contrib/chat/browser/chatVariables'; +import { ICommandService } from 'vs/platform/commands/common/commands'; +import { TestCommandService } from 'vs/editor/test/browser/editorTestServices'; suite('InteractiveChatController', function () { class TestController extends InlineChatController { @@ -136,6 +138,7 @@ suite('InteractiveChatController', function () { [IInlineChatService, new SyncDescriptor(InlineChatServiceImpl)], [IDiffProviderFactoryService, new SyncDescriptor(TestDiffProviderFactoryService)], [IInlineChatSessionService, new SyncDescriptor(InlineChatSessionServiceImpl)], + [ICommandService, new SyncDescriptor(TestCommandService)], [IInlineChatSavingService, new class extends mock() { override markChanged(session: Session): void { // noop diff --git a/src/vs/workbench/contrib/inlineChat/test/browser/inlineChatSession.test.ts b/src/vs/workbench/contrib/inlineChat/test/browser/inlineChatSession.test.ts index 043ea8c80abcb..b28ae6f4ad7ef 100644 --- a/src/vs/workbench/contrib/inlineChat/test/browser/inlineChatSession.test.ts +++ b/src/vs/workbench/contrib/inlineChat/test/browser/inlineChatSession.test.ts @@ -55,6 +55,8 @@ import { IViewsService } from 'vs/workbench/services/views/common/viewsService'; import { TestExtensionService, TestContextService } from 'vs/workbench/test/common/workbenchTestServices'; import { IChatAgentService, ChatAgentService, ChatAgentLocation } from 'vs/workbench/contrib/chat/common/chatAgents'; import { ChatVariablesService } from 'vs/workbench/contrib/chat/browser/chatVariables'; +import { ICommandService } from 'vs/platform/commands/common/commands'; +import { TestCommandService } from 'vs/editor/test/browser/editorTestServices'; suite('InlineChatSession', function () { @@ -89,6 +91,7 @@ suite('InlineChatSession', function () { [IContextKeyService, contextKeyService], [IDiffProviderFactoryService, new SyncDescriptor(TestDiffProviderFactoryService)], [IInlineChatSessionService, new SyncDescriptor(InlineChatSessionServiceImpl)], + [ICommandService, new SyncDescriptor(TestCommandService)], [IInlineChatSavingService, new class extends mock() { override markChanged(session: Session): void { // noop From f6d0e7f6aa79c608fda45f0289f75aeb64a45d47 Mon Sep 17 00:00:00 2001 From: Logan Ramos Date: Thu, 25 Apr 2024 17:26:07 -0700 Subject: [PATCH 005/104] Bump version (#211398) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2fca1caae582e..1f5a34f8e87da 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "code-oss-dev", - "version": "1.89.0", + "version": "1.90.0", "distro": "25c9442cad1fee4c5b7fd96dd526ae00022f881b", "author": { "name": "Microsoft Corporation" From f86d0f7324e0db0682cf8d49af73a98df4c420bd Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Thu, 25 Apr 2024 18:18:09 -0700 Subject: [PATCH 006/104] Exclude product.overrides from hygiene (#211396) --- build/filters.js | 1 + 1 file changed, 1 insertion(+) diff --git a/build/filters.js b/build/filters.js index 0e0c5fcabb8ca..c7be2d818d9bf 100644 --- a/build/filters.js +++ b/build/filters.js @@ -81,6 +81,7 @@ module.exports.indentationFilter = [ '!resources/linux/snap/electron-launch', '!build/ext.js', '!build/npm/gyp/patches/gyp_spectre_mitigation_support.patch', + '!product.overrides.json', // except specific folders '!test/automation/out/**', From c1f470ad5aaaa86ff97cffde4633ea944046edad Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 26 Apr 2024 09:33:23 +0200 Subject: [PATCH 007/104] voice - allow for text to speech (#211006) --- .../workbench/api/browser/mainThreadSpeech.ts | 46 +++++++++- .../workbench/api/common/extHost.api.impl.ts | 1 + .../workbench/api/common/extHost.protocol.ts | 7 +- src/vs/workbench/api/common/extHostSpeech.ts | 41 +++++++++ src/vs/workbench/api/common/extHostTypes.ts | 6 ++ .../chat/test/common/voiceChat.test.ts | 13 ++- .../contrib/speech/browser/speechService.ts | 89 ++++++++++++++++++- .../contrib/speech/common/speechService.ts | 31 +++++++ src/vscode-dts/vscode.proposed.speech.d.ts | 20 ++++- 9 files changed, 248 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/api/browser/mainThreadSpeech.ts b/src/vs/workbench/api/browser/mainThreadSpeech.ts index 56ce1bca62330..fcb28dbc417c0 100644 --- a/src/vs/workbench/api/browser/mainThreadSpeech.ts +++ b/src/vs/workbench/api/browser/mainThreadSpeech.ts @@ -7,13 +7,18 @@ import { Emitter, Event } from 'vs/base/common/event'; import { DisposableStore, IDisposable } from 'vs/base/common/lifecycle'; import { ILogService } from 'vs/platform/log/common/log'; import { ExtHostContext, ExtHostSpeechShape, MainContext, MainThreadSpeechShape } from 'vs/workbench/api/common/extHost.protocol'; -import { IKeywordRecognitionEvent, ISpeechProviderMetadata, ISpeechService, ISpeechToTextEvent } from 'vs/workbench/contrib/speech/common/speechService'; +import { IKeywordRecognitionEvent, ISpeechProviderMetadata, ISpeechService, ISpeechToTextEvent, ITextToSpeechEvent } from 'vs/workbench/contrib/speech/common/speechService'; import { IExtHostContext, extHostNamedCustomer } from 'vs/workbench/services/extensions/common/extHostCustomers'; type SpeechToTextSession = { readonly onDidChange: Emitter; }; +type TextToSpeechSession = { + readonly onDidChange: Emitter; + synthesize(text: string): Promise; +}; + type KeywordRecognitionSession = { readonly onDidChange: Emitter; }; @@ -26,6 +31,7 @@ export class MainThreadSpeech implements MainThreadSpeechShape { private readonly providerRegistrations = new Map(); private readonly speechToTextSessions = new Map(); + private readonly textToSpeechSessions = new Map(); private readonly keywordRecognitionSessions = new Map(); constructor( @@ -66,6 +72,36 @@ export class MainThreadSpeech implements MainThreadSpeechShape { onDidChange: onDidChange.event }; }, + createTextToSpeechSession: (token) => { + if (token.isCancellationRequested) { + return { + onDidChange: Event.None, + synthesize: async () => { } + }; + } + + const disposables = new DisposableStore(); + const session = Math.random(); + + this.proxy.$createTextToSpeechSession(handle, session); + + const onDidChange = disposables.add(new Emitter()); + this.textToSpeechSessions.set(session, { + onDidChange, + synthesize: text => this.proxy.$synthesizeSpeech(session, text) + }); + + disposables.add(token.onCancellationRequested(() => { + this.proxy.$cancelTextToSpeechSession(session); + this.textToSpeechSessions.delete(session); + disposables.dispose(); + })); + + return { + onDidChange: onDidChange.event, + synthesize: text => this.proxy.$synthesizeSpeech(session, text) + }; + }, createKeywordRecognitionSession: token => { if (token.isCancellationRequested) { return { @@ -112,6 +148,11 @@ export class MainThreadSpeech implements MainThreadSpeechShape { providerSession?.onDidChange.fire(event); } + $emitTextToSpeechEvent(session: number, event: ITextToSpeechEvent): void { + const providerSession = this.textToSpeechSessions.get(session); + providerSession?.onDidChange.fire(event); + } + $emitKeywordRecognitionEvent(session: number, event: IKeywordRecognitionEvent): void { const providerSession = this.keywordRecognitionSessions.get(session); providerSession?.onDidChange.fire(event); @@ -124,6 +165,9 @@ export class MainThreadSpeech implements MainThreadSpeechShape { this.speechToTextSessions.forEach(session => session.onDidChange.dispose()); this.speechToTextSessions.clear(); + this.textToSpeechSessions.forEach(session => session.onDidChange.dispose()); + this.textToSpeechSessions.clear(); + this.keywordRecognitionSessions.forEach(session => session.onDidChange.dispose()); this.keywordRecognitionSessions.clear(); } diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index 117a610839515..2b49b0f59d626 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -1698,6 +1698,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I DebugThread: extHostTypes.DebugThread, RelatedInformationType: extHostTypes.RelatedInformationType, SpeechToTextStatus: extHostTypes.SpeechToTextStatus, + TextToSpeechStatus: extHostTypes.TextToSpeechStatus, PartialAcceptTriggerKind: extHostTypes.PartialAcceptTriggerKind, KeywordRecognitionStatus: extHostTypes.KeywordRecognitionStatus, ChatResponseMarkdownPart: extHostTypes.ChatResponseMarkdownPart, diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index e847d35fd9515..16e6fb46787ea 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -64,7 +64,7 @@ import { ICellRange } from 'vs/workbench/contrib/notebook/common/notebookRange'; import { InputValidationType } from 'vs/workbench/contrib/scm/common/scm'; import { IWorkspaceSymbol, NotebookPriorityInfo } from 'vs/workbench/contrib/search/common/search'; import { IRawClosedNotebookFileMatch } from 'vs/workbench/contrib/search/common/searchNotebookHelpers'; -import { IKeywordRecognitionEvent, ISpeechProviderMetadata, ISpeechToTextEvent } from 'vs/workbench/contrib/speech/common/speechService'; +import { IKeywordRecognitionEvent, ISpeechProviderMetadata, ISpeechToTextEvent, ITextToSpeechEvent } from 'vs/workbench/contrib/speech/common/speechService'; import { CoverageDetails, ExtensionRunTestsRequest, ICallProfileRunHandler, IFileCoverage, ISerializedTestResults, IStartControllerTests, ITestItem, ITestMessage, ITestRunProfile, ITestRunTask, ResolvedTestRunRequest, TestResultState, TestsDiffOp } from 'vs/workbench/contrib/testing/common/testTypes'; import { Timeline, TimelineChangeEvent, TimelineOptions, TimelineProviderDescriptor } from 'vs/workbench/contrib/timeline/common/timeline'; import { TypeHierarchyItem } from 'vs/workbench/contrib/typeHierarchy/common/typeHierarchy'; @@ -1181,6 +1181,7 @@ export interface MainThreadSpeechShape extends IDisposable { $unregisterProvider(handle: number): void; $emitSpeechToTextEvent(session: number, event: ISpeechToTextEvent): void; + $emitTextToSpeechEvent(session: number, event: ITextToSpeechEvent): void; $emitKeywordRecognitionEvent(session: number, event: IKeywordRecognitionEvent): void; } @@ -1188,6 +1189,10 @@ export interface ExtHostSpeechShape { $createSpeechToTextSession(handle: number, session: number, language?: string): Promise; $cancelSpeechToTextSession(session: number): Promise; + $createTextToSpeechSession(handle: number, session: number): Promise; + $synthesizeSpeech(session: number, text: string): Promise; + $cancelTextToSpeechSession(session: number): Promise; + $createKeywordRecognitionSession(handle: number, session: number): Promise; $cancelKeywordRecognitionSession(session: number): Promise; } diff --git a/src/vs/workbench/api/common/extHostSpeech.ts b/src/vs/workbench/api/common/extHostSpeech.ts index 9093f63e3abc5..abc56cedc087a 100644 --- a/src/vs/workbench/api/common/extHostSpeech.ts +++ b/src/vs/workbench/api/common/extHostSpeech.ts @@ -17,6 +17,7 @@ export class ExtHostSpeech implements ExtHostSpeechShape { private readonly providers = new Map(); private readonly sessions = new Map(); + private readonly synthesizers = new Map(); constructor( mainContext: IMainContext @@ -52,6 +53,46 @@ export class ExtHostSpeech implements ExtHostSpeechShape { this.sessions.delete(session); } + async $createTextToSpeechSession(handle: number, session: number): Promise { + const provider = this.providers.get(handle); + if (!provider) { + return; + } + + const disposables = new DisposableStore(); + + const cts = new CancellationTokenSource(); + this.sessions.set(session, cts); + + const textToSpeech = disposables.add(provider.provideTextToSpeechSession(cts.token)); + this.synthesizers.set(session, textToSpeech); + + disposables.add(textToSpeech.onDidChange(e => { + if (cts.token.isCancellationRequested) { + return; + } + + this.proxy.$emitTextToSpeechEvent(session, e); + })); + + disposables.add(cts.token.onCancellationRequested(() => disposables.dispose())); + } + + async $synthesizeSpeech(session: number, text: string): Promise { + const synthesizer = this.synthesizers.get(session); + if (!synthesizer) { + return; + } + + synthesizer.synthesize(text); + } + + async $cancelTextToSpeechSession(session: number): Promise { + this.sessions.get(session)?.dispose(true); + this.sessions.delete(session); + this.synthesizers.delete(session); + } + async $createKeywordRecognitionSession(handle: number, session: number): Promise { const provider = this.providers.get(handle); if (!provider) { diff --git a/src/vs/workbench/api/common/extHostTypes.ts b/src/vs/workbench/api/common/extHostTypes.ts index ff0d6f9e5b981..551e1289cc9a7 100644 --- a/src/vs/workbench/api/common/extHostTypes.ts +++ b/src/vs/workbench/api/common/extHostTypes.ts @@ -4484,6 +4484,12 @@ export enum SpeechToTextStatus { Error = 5 } +export enum TextToSpeechStatus { + Started = 1, + Stopped = 2, + Error = 3 +} + export enum KeywordRecognitionStatus { Recognized = 1, Stopped = 2 diff --git a/src/vs/workbench/contrib/chat/test/common/voiceChat.test.ts b/src/vs/workbench/contrib/chat/test/common/voiceChat.test.ts index 10b5b660fd4ee..5e94b169a0647 100644 --- a/src/vs/workbench/contrib/chat/test/common/voiceChat.test.ts +++ b/src/vs/workbench/contrib/chat/test/common/voiceChat.test.ts @@ -15,7 +15,7 @@ import { ChatAgentLocation, IChatAgent, IChatAgentCommand, IChatAgentData, IChat import { IChatModel } from 'vs/workbench/contrib/chat/common/chatModel'; import { IChatProgress, IChatFollowup } from 'vs/workbench/contrib/chat/common/chatService'; import { IVoiceChatSessionOptions, IVoiceChatTextEvent, VoiceChatService } from 'vs/workbench/contrib/chat/common/voiceChat'; -import { ISpeechProvider, ISpeechService, ISpeechToTextEvent, ISpeechToTextSession, KeywordRecognitionStatus, SpeechToTextStatus } from 'vs/workbench/contrib/speech/common/speechService'; +import { ISpeechProvider, ISpeechService, ISpeechToTextEvent, ISpeechToTextSession, ITextToSpeechSession, KeywordRecognitionStatus, SpeechToTextStatus } from 'vs/workbench/contrib/speech/common/speechService'; import { nullExtensionDescription } from 'vs/workbench/services/extensions/common/extensions'; suite('VoiceChat', () => { @@ -75,6 +75,7 @@ suite('VoiceChat', () => { readonly hasSpeechProvider = true; readonly hasActiveSpeechToTextSession = false; + readonly hasActiveTextToSpeechSession = false; readonly hasActiveKeywordRecognition = false; registerSpeechProvider(identifier: string, provider: ISpeechProvider): IDisposable { throw new Error('Method not implemented.'); } @@ -87,6 +88,16 @@ suite('VoiceChat', () => { }; } + onDidStartTextToSpeechSession = Event.None; + onDidEndTextToSpeechSession = Event.None; + + async createTextToSpeechSession(token: CancellationToken): Promise { + return { + onDidChange: Event.None, + synthesize: async () => { } + }; + } + onDidStartKeywordRecognition = Event.None; onDidEndKeywordRecognition = Event.None; recognizeKeyword(token: CancellationToken): Promise { throw new Error('Method not implemented.'); } diff --git a/src/vs/workbench/contrib/speech/browser/speechService.ts b/src/vs/workbench/contrib/speech/browser/speechService.ts index 94a45671ea3e1..25d5c0ce95198 100644 --- a/src/vs/workbench/contrib/speech/browser/speechService.ts +++ b/src/vs/workbench/contrib/speech/browser/speechService.ts @@ -12,7 +12,7 @@ import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { ILogService } from 'vs/platform/log/common/log'; import { IHostService } from 'vs/workbench/services/host/browser/host'; import { DeferredPromise } from 'vs/base/common/async'; -import { ISpeechService, ISpeechProvider, HasSpeechProvider, ISpeechToTextSession, SpeechToTextInProgress, IKeywordRecognitionSession, KeywordRecognitionStatus, SpeechToTextStatus, speechLanguageConfigToLanguage, SPEECH_LANGUAGE_CONFIG } from 'vs/workbench/contrib/speech/common/speechService'; +import { ISpeechService, ISpeechProvider, HasSpeechProvider, ISpeechToTextSession, SpeechToTextInProgress, IKeywordRecognitionSession, KeywordRecognitionStatus, SpeechToTextStatus, speechLanguageConfigToLanguage, SPEECH_LANGUAGE_CONFIG, ITextToSpeechSession, TextToSpeechInProgress, TextToSpeechStatus } from 'vs/workbench/contrib/speech/common/speechService'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ExtensionsRegistry } from 'vs/workbench/services/extensions/common/extensionsRegistry'; @@ -126,6 +126,8 @@ export class SpeechService extends Disposable implements ISpeechService { this._onDidChangeHasSpeechProvider.fire(); } + //#region Transcription + private readonly _onDidStartSpeechToTextSession = this._register(new Emitter()); readonly onDidStartSpeechToTextSession = this._onDidStartSpeechToTextSession.event; @@ -236,6 +238,89 @@ export class SpeechService extends Disposable implements ISpeechService { return provider; } + //#endregion + + //#region Synthesizer + + private readonly _onDidStartTextToSpeechSession = this._register(new Emitter()); + readonly onDidStartTextToSpeechSession = this._onDidStartTextToSpeechSession.event; + + private readonly _onDidEndTextToSpeechSession = this._register(new Emitter()); + readonly onDidEndTextToSpeechSession = this._onDidEndTextToSpeechSession.event; + + private _activeTextToSpeechSession: ITextToSpeechSession | undefined = undefined; + get hasActiveTextToSpeechSession() { return !!this._activeTextToSpeechSession; } + + private readonly textToSpeechInProgress = TextToSpeechInProgress.bindTo(this.contextKeyService); + + async createTextToSpeechSession(token: CancellationToken, context: string = 'speech'): Promise { + const provider = await this.getProvider(); + + const session = this._activeTextToSpeechSession = provider.createTextToSpeechSession(token); + + const sessionStart = Date.now(); + let sessionError = false; + + const disposables = new DisposableStore(); + + const onSessionStoppedOrCanceled = () => { + if (session === this._activeTextToSpeechSession) { + this._activeTextToSpeechSession = undefined; + this.textToSpeechInProgress.reset(); + this._onDidEndTextToSpeechSession.fire(); + + type TextToSpeechSessionClassification = { + owner: 'bpasero'; + comment: 'An event that fires when a text to speech session is created'; + context: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'Context of the session.' }; + sessionDuration: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'Duration of the session.' }; + sessionError: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'If speech resulted in error.' }; + }; + type TextToSpeechSessionEvent = { + context: string; + sessionDuration: number; + sessionError: boolean; + }; + this.telemetryService.publicLog2('textToSpeechSession', { + context, + sessionDuration: Date.now() - sessionStart, + sessionError + }); + } + + disposables.dispose(); + }; + + disposables.add(token.onCancellationRequested(() => onSessionStoppedOrCanceled())); + if (token.isCancellationRequested) { + onSessionStoppedOrCanceled(); + } + + disposables.add(session.onDidChange(e => { + switch (e.status) { + case TextToSpeechStatus.Started: + if (session === this._activeTextToSpeechSession) { + this.textToSpeechInProgress.set(true); + this._onDidStartTextToSpeechSession.fire(); + } + break; + case TextToSpeechStatus.Stopped: + onSessionStoppedOrCanceled(); + break; + case TextToSpeechStatus.Error: + this.logService.error(`Speech provider error in text to speech session: ${e.text}`); + sessionError = true; + break; + } + })); + + return session; + } + + //#endregion + + //#region Keyword Recognition + private readonly _onDidStartKeywordRecognition = this._register(new Emitter()); readonly onDidStartKeywordRecognition = this._onDidStartKeywordRecognition.event; @@ -344,4 +429,6 @@ export class SpeechService extends Disposable implements ISpeechService { onSessionStoppedOrCanceled(); } } + + //#endregion } diff --git a/src/vs/workbench/contrib/speech/common/speechService.ts b/src/vs/workbench/contrib/speech/common/speechService.ts index 4f260469983c3..4bd76b641aa42 100644 --- a/src/vs/workbench/contrib/speech/common/speechService.ts +++ b/src/vs/workbench/contrib/speech/common/speechService.ts @@ -16,6 +16,7 @@ export const ISpeechService = createDecorator('speechService'); export const HasSpeechProvider = new RawContextKey('hasSpeechProvider', false, { type: 'string', description: localize('hasSpeechProvider', "A speech provider is registered to the speech service.") }); export const SpeechToTextInProgress = new RawContextKey('speechToTextInProgress', false, { type: 'string', description: localize('speechToTextInProgress', "A speech-to-text session is in progress.") }); +export const TextToSpeechInProgress = new RawContextKey('textToSpeechInProgress', false, { type: 'string', description: localize('textToSpeechInProgress', "A text-to-speech session is in progress.") }); export interface ISpeechProviderMetadata { readonly extension: ExtensionIdentifier; @@ -39,6 +40,23 @@ export interface ISpeechToTextSession { readonly onDidChange: Event; } +export enum TextToSpeechStatus { + Started = 1, + Stopped = 2, + Error = 3 +} + +export interface ITextToSpeechEvent { + readonly status: TextToSpeechStatus; + readonly text?: string; +} + +export interface ITextToSpeechSession { + readonly onDidChange: Event; + + synthesize(text: string): void; +} + export enum KeywordRecognitionStatus { Recognized = 1, Stopped = 2, @@ -62,6 +80,7 @@ export interface ISpeechProvider { readonly metadata: ISpeechProviderMetadata; createSpeechToTextSession(token: CancellationToken, options?: ISpeechToTextSessionOptions): ISpeechToTextSession; + createTextToSpeechSession(token: CancellationToken): ITextToSpeechSession; createKeywordRecognitionSession(token: CancellationToken): IKeywordRecognitionSession; } @@ -86,6 +105,18 @@ export interface ISpeechService { */ createSpeechToTextSession(token: CancellationToken, context?: string): Promise; + readonly onDidStartTextToSpeechSession: Event; + readonly onDidEndTextToSpeechSession: Event; + + readonly hasActiveTextToSpeechSession: boolean; + + /** + * Creates a synthesizer to synthesize speech from text. The returned + * session object provides a method to synthesize text and listen for + * events. + */ + createTextToSpeechSession(token: CancellationToken, context?: string): Promise; + readonly onDidStartKeywordRecognition: Event; readonly onDidEndKeywordRecognition: Event; diff --git a/src/vscode-dts/vscode.proposed.speech.d.ts b/src/vscode-dts/vscode.proposed.speech.d.ts index 9ece68528b98c..4e0ad0031ce7c 100644 --- a/src/vscode-dts/vscode.proposed.speech.d.ts +++ b/src/vscode-dts/vscode.proposed.speech.d.ts @@ -5,8 +5,6 @@ declare module 'vscode' { - // todo@bpasero work in progress speech API - export interface SpeechToTextOptions { readonly language?: string; } @@ -28,6 +26,23 @@ declare module 'vscode' { readonly onDidChange: Event; } + export enum TextToSpeechStatus { + Started = 1, + Stopped = 2, + Error = 3 + } + + export interface TextToSpeechEvent { + readonly status: TextToSpeechStatus; + readonly text?: string; + } + + export interface TextToSpeechSession extends Disposable { + readonly onDidChange: Event; + + synthesize(text: string): void; + } + export enum KeywordRecognitionStatus { Recognized = 1, Stopped = 2 @@ -44,6 +59,7 @@ declare module 'vscode' { export interface SpeechProvider { provideSpeechToTextSession(token: CancellationToken, options?: SpeechToTextOptions): SpeechToTextSession; + provideTextToSpeechSession(token: CancellationToken): TextToSpeechSession; provideKeywordRecognitionSession(token: CancellationToken): KeywordRecognitionSession; } From 82de0899cc16363ff49413dfe6176f27e2c44a46 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 26 Apr 2024 09:33:49 +0200 Subject: [PATCH 008/104] Focus into Side Bar commands don't focus the sidebar if the sidebar wasn't already visible (fix #193737) (#211417) --- src/vs/workbench/browser/parts/sidebar/sidebarActions.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/vs/workbench/browser/parts/sidebar/sidebarActions.ts b/src/vs/workbench/browser/parts/sidebar/sidebarActions.ts index 8cafc0dbbcd88..cd4811f83e6b2 100644 --- a/src/vs/workbench/browser/parts/sidebar/sidebarActions.ts +++ b/src/vs/workbench/browser/parts/sidebar/sidebarActions.ts @@ -37,7 +37,6 @@ export class FocusSideBarAction extends Action2 { // Show side bar if (!layoutService.isVisible(Parts.SIDEBAR_PART)) { layoutService.setPartHidden(false, Parts.SIDEBAR_PART); - return; } // Focus into active viewlet From 8e659485106166c37b106b2821276c67e6dde608 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 26 Apr 2024 09:34:03 +0200 Subject: [PATCH 009/104] Exact matches are hard to find in outline (fix #187921) (#211419) --- src/vs/base/common/filters.ts | 2 +- src/vs/base/test/common/filters.test.ts | 12 ++++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/vs/base/common/filters.ts b/src/vs/base/common/filters.ts index 03cb85813cc83..8c02823852c7a 100644 --- a/src/vs/base/common/filters.ts +++ b/src/vs/base/common/filters.ts @@ -764,7 +764,7 @@ export function fuzzyScore(pattern: string, patternLow: string, patternStart: nu result.push(column); } - if (wordLen === patternLen && options.boostFullMatch) { + if (wordLen - wordStart === patternLen && options.boostFullMatch) { // the word matches the pattern with all characters! // giving the score a total match boost (to come up ahead other words) result[0] += 2; diff --git a/src/vs/base/test/common/filters.test.ts b/src/vs/base/test/common/filters.test.ts index 135330f7044bd..5bfe3856226f5 100644 --- a/src/vs/base/test/common/filters.test.ts +++ b/src/vs/base/test/common/filters.test.ts @@ -580,8 +580,16 @@ suite('Filters', () => { const a = 'createModelServices'; const b = 'create'; - const aBoost = fuzzyScore(prefix, prefix, 0, a, a.toLowerCase(), 0, { boostFullMatch: true, firstMatchCanBeWeak: true }); - const bBoost = fuzzyScore(prefix, prefix, 0, b, b.toLowerCase(), 0, { boostFullMatch: true, firstMatchCanBeWeak: true }); + let aBoost = fuzzyScore(prefix, prefix, 0, a, a.toLowerCase(), 0, { boostFullMatch: true, firstMatchCanBeWeak: true }); + let bBoost = fuzzyScore(prefix, prefix, 0, b, b.toLowerCase(), 0, { boostFullMatch: true, firstMatchCanBeWeak: true }); + assert.ok(aBoost); + assert.ok(bBoost); + assert.ok(aBoost[0] < bBoost[0]); + + // also works with wordStart > 0 (/~https://github.com/microsoft/vscode/issues/187921) + const wordPrefix = '$(symbol-function) '; + aBoost = fuzzyScore(prefix, prefix, 0, `${wordPrefix}${a}`, `${wordPrefix}${a}`.toLowerCase(), wordPrefix.length, { boostFullMatch: true, firstMatchCanBeWeak: true }); + bBoost = fuzzyScore(prefix, prefix, 0, `${wordPrefix}${b}`, `${wordPrefix}${b}`.toLowerCase(), wordPrefix.length, { boostFullMatch: true, firstMatchCanBeWeak: true }); assert.ok(aBoost); assert.ok(bBoost); assert.ok(aBoost[0] < bBoost[0]); From e0e7aeca174ec2a064a35b0186a1b08515f1cd30 Mon Sep 17 00:00:00 2001 From: Justin Chen <54879025+justschen@users.noreply.github.com> Date: Fri, 26 Apr 2024 16:16:10 +0800 Subject: [PATCH 010/104] additional lightbulb telemetry for insiders (#211407) * added back lightbulb telemetry * some cleanup --- .../codeAction/browser/lightBulbWidget.ts | 32 ++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/src/vs/editor/contrib/codeAction/browser/lightBulbWidget.ts b/src/vs/editor/contrib/codeAction/browser/lightBulbWidget.ts index 68420ef0fd107..3e62c4c02811f 100644 --- a/src/vs/editor/contrib/codeAction/browser/lightBulbWidget.ts +++ b/src/vs/editor/contrib/codeAction/browser/lightBulbWidget.ts @@ -7,6 +7,7 @@ import * as dom from 'vs/base/browser/dom'; import { Gesture } from 'vs/base/browser/touch'; import { Codicon } from 'vs/base/common/codicons'; import { Emitter, Event } from 'vs/base/common/event'; +import { HierarchicalKind } from 'vs/base/common/hierarchicalKind'; import { Disposable } from 'vs/base/common/lifecycle'; import { ThemeIcon } from 'vs/base/common/themables'; import 'vs/css!./lightBulbWidget'; @@ -15,10 +16,11 @@ import { EditorOption } from 'vs/editor/common/config/editorOptions'; import { IPosition } from 'vs/editor/common/core/position'; import { computeIndentLevel } from 'vs/editor/common/model/utils'; import { autoFixCommandId, quickFixCommandId } from 'vs/editor/contrib/codeAction/browser/codeAction'; -import type { CodeActionSet, CodeActionTrigger } from 'vs/editor/contrib/codeAction/common/types'; +import { CodeActionKind, CodeActionSet, CodeActionTrigger } from 'vs/editor/contrib/codeAction/common/types'; import * as nls from 'vs/nls'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; +import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; namespace LightBulbState { @@ -64,6 +66,7 @@ export class LightBulbWidget extends Disposable implements IContentWidget { private readonly _editor: ICodeEditor, @IKeybindingService private readonly _keybindingService: IKeybindingService, @ICommandService commandService: ICommandService, + @ITelemetryService private readonly _telemetryService: ITelemetryService, ) { super(); @@ -189,6 +192,33 @@ export class LightBulbWidget extends Disposable implements IContentWidget { position: { lineNumber: effectiveLineNumber, column: effectiveColumnNumber }, preference: LightBulbWidget._posPref }); + + const validActions = actions.validActions; + const actionKind = actions.validActions[0].action.kind; + if (validActions.length !== 1 || !actionKind) { + this._editor.layoutContentWidget(this); + return; + } + + const hierarchicalKind = new HierarchicalKind(actionKind); + + if (CodeActionKind.RefactorMove.contains(hierarchicalKind)) { + // Telemetry for showing code actions here. only log on `showLightbulb`. Logs when code action list is quit out. + type ShowCodeActionListEvent = { + codeActionListLength: number; + }; + + type ShowListEventClassification = { + codeActionListLength: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The length of the code action list when quit out. Can be from any code action menu.' }; + owner: 'justschen'; + comment: 'Event used to gain insights into how often the lightbulb only contains one code action, namely the move to code action. '; + }; + + this._telemetryService.publicLog2('lightbulbWidget.moveToCodeActions', { + codeActionListLength: validActions.length, + }); + } + this._editor.layoutContentWidget(this); } From e229ffdb0e90cc49d9e5b92410ac2fb866533a81 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Fri, 26 Apr 2024 10:58:24 +0200 Subject: [PATCH 011/104] Fix tree selection context and command args (#211429) Fixes #210046 --- src/vs/workbench/browser/parts/views/treeView.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/browser/parts/views/treeView.ts b/src/vs/workbench/browser/parts/views/treeView.ts index 9ac5d9dbad240..ee77e91b7333b 100644 --- a/src/vs/workbench/browser/parts/views/treeView.ts +++ b/src/vs/workbench/browser/parts/views/treeView.ts @@ -801,9 +801,10 @@ abstract class AbstractTreeView extends Disposable implements ITreeView { this.tree!.setFocus([node]); let selected = this.canSelectMany ? this.getSelection() : []; - if (selected.length === 0) { + if (!selected.find(item => item.handle === node.handle)) { selected = [node]; } + const actions = treeMenus.getResourceContextActions(selected); if (!actions.length) { return; @@ -1567,8 +1568,8 @@ class MultipleSelectionActionRunner extends ActionRunner { }); } - if (!actionInSelected && selectionHandleArgs && selectionHandleArgs.length > 0) { - context = selectionHandleArgs[0]; + if (!actionInSelected && selectionHandleArgs) { + selectionHandleArgs = undefined; } await action.run(context, selectionHandleArgs); From edb368fc43903ec87e3167ff5fd2b40736eb2a52 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 26 Apr 2024 12:22:41 +0200 Subject: [PATCH 012/104] Middle-clicking nonexistent tab pastes text into the code editor (fix #201696) (#211436) --- .../browser/parts/editor/multiEditorTabsControl.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/browser/parts/editor/multiEditorTabsControl.ts b/src/vs/workbench/browser/parts/editor/multiEditorTabsControl.ts index 12d77fb90547c..706924c23e71a 100644 --- a/src/vs/workbench/browser/parts/editor/multiEditorTabsControl.ts +++ b/src/vs/workbench/browser/parts/editor/multiEditorTabsControl.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import 'vs/css!./media/multieditortabscontrol'; -import { isMacintosh, isWindows } from 'vs/base/common/platform'; +import { isLinux, isMacintosh, isWindows } from 'vs/base/common/platform'; import { shorten } from 'vs/base/common/labels'; import { EditorResourceAccessor, Verbosity, IEditorPartOptions, SideBySideEditor, DEFAULT_EDITOR_ASSOCIATION, EditorInputCapabilities, IUntypedEditorInput, preventEditorClose, EditorCloseMethod, EditorsOrder, IToolbarActions } from 'vs/workbench/common/editor'; import { EditorInput } from 'vs/workbench/common/editor/editorInput'; @@ -316,6 +316,15 @@ export class MultiEditorTabsControl extends EditorTabsControl { } })); + // Prevent auto-pasting (/~https://github.com/microsoft/vscode/issues/201696) + if (isLinux) { + this._register(addDisposableListener(tabsContainer, EventType.MOUSE_UP, e => { + if (e.button === 1) { + e.preventDefault(); + } + })); + } + // Drag & Drop support let lastDragEvent: DragEvent | undefined = undefined; let isNewWindowOperation = false; From 5c213a1e84928c7a7d11ca5b282ca602d40c1352 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Fri, 26 Apr 2024 13:52:52 +0200 Subject: [PATCH 013/104] Update grammars (#211439) --- extensions/dart/cgmanifest.json | 2 +- extensions/dart/syntaxes/dart.tmLanguage.json | 46 +- extensions/go/cgmanifest.json | 4 +- extensions/go/syntaxes/go.tmLanguage.json | 16 +- extensions/julia/cgmanifest.json | 2 +- .../julia/syntaxes/julia.tmLanguage.json | 4 +- extensions/latex/cgmanifest.json | 2 +- .../latex/syntaxes/LaTeX.tmLanguage.json | 37 +- extensions/latex/syntaxes/TeX.tmLanguage.json | 20 +- .../cpp-grammar-bailout.tmLanguage.json | 2338 ++++++++++------- extensions/less/cgmanifest.json | 2 +- extensions/less/syntaxes/less.tmLanguage.json | 4 +- extensions/lua/cgmanifest.json | 2 +- extensions/lua/syntaxes/lua.tmLanguage.json | 56 +- extensions/razor/cgmanifest.json | 2 +- .../razor/syntaxes/cshtml.tmLanguage.json | 24 +- extensions/shellscript/cgmanifest.json | 4 +- .../syntaxes/shell-unix-bash.tmLanguage.json | 95 +- .../test/colorize-results/test_go.json | 2 +- 19 files changed, 1614 insertions(+), 1048 deletions(-) diff --git a/extensions/dart/cgmanifest.json b/extensions/dart/cgmanifest.json index 9c90588adf182..df4e4f0aae967 100644 --- a/extensions/dart/cgmanifest.json +++ b/extensions/dart/cgmanifest.json @@ -6,7 +6,7 @@ "git": { "name": "dart-lang/dart-syntax-highlight", "repositoryUrl": "/~https://github.com/dart-lang/dart-syntax-highlight", - "commitHash": "272e2f89f85073c04b7e15b582257f76d2489970" + "commitHash": "bb8f7eebf5a1028e70dbebcf35cfef738dddc7fe" } }, "licenseDetail": [ diff --git a/extensions/dart/syntaxes/dart.tmLanguage.json b/extensions/dart/syntaxes/dart.tmLanguage.json index cc9dee8d2754e..5a4a9393bc749 100644 --- a/extensions/dart/syntaxes/dart.tmLanguage.json +++ b/extensions/dart/syntaxes/dart.tmLanguage.json @@ -4,7 +4,7 @@ "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "/~https://github.com/dart-lang/dart-syntax-highlight/commit/272e2f89f85073c04b7e15b582257f76d2489970", + "version": "/~https://github.com/dart-lang/dart-syntax-highlight/commit/bb8f7eebf5a1028e70dbebcf35cfef738dddc7fe", "name": "Dart", "scopeName": "source.dart", "patterns": [ @@ -14,7 +14,7 @@ }, { "name": "meta.declaration.dart", - "begin": "^\\w*\\b(library|import|part of|part|export)\\b", + "begin": "^\\w*\\b(augment\\s+library|library|import\\s+augment|import|part\\s+of|part|export)\\b", "beginCaptures": { "0": { "name": "keyword.other.import.dart" @@ -208,7 +208,7 @@ }, { "name": "variable.language.dart", - "match": "(?|(?=\\\\end\\{(?:minted|cppcode)\\})", - "beginCaptures": { - "0": { - "name": "punctuation.section.angle-brackets.begin.template.call.cpp" - } - }, - "endCaptures": { - "0": { - "name": "punctuation.section.angle-brackets.end.template.call.cpp" - } - }, - "name": "meta.template.call.cpp", - "patterns": [ - { - "include": "#template_call_context" - } - ] + "include": "#template_call_range_helper" }, { "match": "(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*", @@ -2150,14 +2133,14 @@ "name": "entity.name.scope-resolution.type.cpp" }, { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, "12": { "patterns": [ { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, @@ -2420,308 +2403,53 @@ }, "name": "meta.preprocessor.import.cpp" }, - "d9bc4796b0b_preprocessor_number_literal": { - "match": "(?|(?=\\\\end\\{(?:minted|cppcode)\\})", - "beginCaptures": { - "0": { - "name": "punctuation.section.angle-brackets.begin.template.call.cpp" - } - }, - "endCaptures": { - "0": { - "name": "punctuation.section.angle-brackets.end.template.call.cpp" - } - }, - "name": "meta.template.call.cpp", - "patterns": [ - { - "include": "#template_call_context" - } - ] + "include": "#template_call_range_helper" }, { "match": "(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*", @@ -4261,14 +3972,14 @@ "name": "entity.name.scope-resolution.type.cpp" }, { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, "24": { "patterns": [ { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, @@ -4404,7 +4115,7 @@ "51": { "patterns": [ { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, @@ -4527,24 +4238,7 @@ "include": "#scope_resolution_inner_generated" }, { - "begin": "<", - "end": ">|(?=\\\\end\\{(?:minted|cppcode)\\})", - "beginCaptures": { - "0": { - "name": "punctuation.section.angle-brackets.begin.template.call.cpp" - } - }, - "endCaptures": { - "0": { - "name": "punctuation.section.angle-brackets.end.template.call.cpp" - } - }, - "name": "meta.template.call.cpp", - "patterns": [ - { - "include": "#template_call_context" - } - ] + "include": "#template_call_range_helper" }, { "match": "(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*", @@ -4605,14 +4299,14 @@ "name": "entity.name.scope-resolution.type.cpp" }, { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, "17": { "patterns": [ { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, @@ -4686,7 +4380,7 @@ }, "function_pointer": { "begin": "(\\s*+((?:(?:(?:\\[\\[.*?\\]\\]|__attribute(?:__)?\\s*\\(\\s*\\(.*?\\)\\s*\\))|__declspec\\(.*?\\))|alignas\\(.*?\\))(?!\\)))?((?:(?:(?:\\s*+(\\/\\*)((?:[^\\*]++|\\*+(?!\\/))*+(\\*\\/))\\s*+)+)|(?:\\s++)|(?<=\\W)|(?=\\W)|^|(?:\\n?$)|\\A|\\Z))(?:(?:(?:(?:unsigned)|(?:signed)|(?:short)|(?:long))|(?:(?:struct)|(?:class)|(?:union)|(?:enum)))((?:(?:(?:\\s*+(\\/\\*)((?:[^\\*]++|\\*+(?!\\/))*+(\\*\\/))\\s*+)+)|(?:\\s++)|(?<=\\W)|(?=\\W)|^|(?:\\n?$)|\\A|\\Z)))*(?:((?:::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|thread_local|dynamic_cast|synchronized|static_cast|const_cast|consteval|co_return|protected|constinit|constexpr|co_return|consteval|namespace|constexpr|constexpr|co_await|explicit|volatile|noexcept|co_yield|noexcept|noexcept|requires|typename|decltype|operator|template|continue|co_await|co_yield|volatile|register|restrict|reflexpr|mutable|alignof|include|private|defined|typedef|_Pragma|__asm__|concept|mutable|warning|default|virtual|alignas|public|sizeof|delete|not_eq|bitand|and_eq|xor_eq|typeid|switch|return|struct|static|extern|inline|friend|ifndef|define|pragma|export|import|module|catch|throw|const|or_eq|compl|while|ifdef|const|bitor|union|class|undef|error|break|using|endif|goto|line|enum|this|case|else|elif|else|not|try|for|asm|and|xor|new|do|if|or|if)\\b)(?|(?:(?:[^'\"<>\\/]|\\/[^*])++))*>)\\s*+)?::)*+)((?:(?:(?:\\s*+(\\/\\*)((?:[^\\*]++|\\*+(?!\\/))*+(\\*\\/))\\s*+)+)|(?:\\s++)|(?<=\\W)|(?=\\W)|^|(?:\\n?$)|\\A|\\Z)))?(?!(?:(?:transaction_safe_dynamic)|(?:__has_cpp_attribute)|(?:reinterpret_cast)|(?:transaction_safe)|(?:atomic_noexcept)|(?:atomic_commit)|(?:__has_include)|(?:atomic_cancel)|(?:synchronized)|(?:thread_local)|(?:dynamic_cast)|(?:static_cast)|(?:const_cast)|(?:constexpr)|(?:co_return)|(?:constinit)|(?:namespace)|(?:protected)|(?:consteval)|(?:constexpr)|(?:constexpr)|(?:co_return)|(?:consteval)|(?:co_await)|(?:continue)|(?:template)|(?:reflexpr)|(?:volatile)|(?:register)|(?:co_await)|(?:co_yield)|(?:restrict)|(?:noexcept)|(?:volatile)|(?:override)|(?:explicit)|(?:decltype)|(?:operator)|(?:noexcept)|(?:noexcept)|(?:typename)|(?:requires)|(?:co_yield)|(?:nullptr)|(?:alignof)|(?:alignas)|(?:default)|(?:mutable)|(?:virtual)|(?:mutable)|(?:private)|(?:include)|(?:warning)|(?:_Pragma)|(?:defined)|(?:typedef)|(?:__asm__)|(?:concept)|(?:define)|(?:module)|(?:sizeof)|(?:switch)|(?:delete)|(?:pragma)|(?:and_eq)|(?:inline)|(?:xor_eq)|(?:typeid)|(?:import)|(?:extern)|(?:public)|(?:bitand)|(?:static)|(?:export)|(?:return)|(?:friend)|(?:ifndef)|(?:not_eq)|(?:false)|(?:final)|(?:break)|(?:const)|(?:catch)|(?:endif)|(?:ifdef)|(?:undef)|(?:error)|(?:audit)|(?:while)|(?:using)|(?:axiom)|(?:or_eq)|(?:compl)|(?:throw)|(?:bitor)|(?:const)|(?:line)|(?:case)|(?:else)|(?:this)|(?:true)|(?:goto)|(?:else)|(?:NULL)|(?:elif)|(?:new)|(?:asm)|(?:xor)|(?:and)|(?:try)|(?:not)|(?:for)|(?:do)|(?:if)|(?:or)|(?:if))\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\b((?|(?:(?:[^'\"<>\\/]|\\/[^*])++))*>)?(?![\\w<:.]))(((?:(?:(?:\\s*+(\\/\\*)((?:[^\\*]++|\\*+(?!\\/))*+(\\*\\/))\\s*+)+)|(?:\\s++)|(?<=\\W)|(?=\\W)|^|(?:\\n?$)|\\A|\\Z))?(?:(?:&|\\*)((?:(?:(?:\\s*+(\\/\\*)((?:[^\\*]++|\\*+(?!\\/))*+(\\*\\/))\\s*+)+)|(?:\\s++)|(?<=\\W)|(?=\\W)|^|(?:\\n?$)|\\A|\\Z)))*(?:&|\\*))?((?:(?:(?:\\s*+(\\/\\*)((?:[^\\*]++|\\*+(?!\\/))*+(\\*\\/))\\s*+)+)|(?:\\s++)|(?<=\\W)|(?=\\W)|^|(?:\\n?$)|\\A|\\Z))(\\()(\\*)(?:\\s+)?((?:(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)?)(?:\\s+)?(?:(\\[)(\\w*)(\\])(?:\\s+)?)*(\\))(?:\\s+)?(\\()", - "end": "(\\))((?:(?:(?:\\s*+(\\/\\*)((?:[^\\*]++|\\*+(?!\\/))*+(\\*\\/))\\s*+)+)|(?:\\s++)|(?<=\\W)|(?=\\W)|^|(?:\\n?$)|\\A|\\Z))(?=[{=,);>]|\\n)(?!\\()|(?=\\\\end\\{(?:minted|cppcode)\\})", + "end": "(\\))((?:(?:(?:\\s*+(\\/\\*)((?:[^\\*]++|\\*+(?!\\/))*+(\\*\\/))\\s*+)+)|(?:\\s++)|(?<=\\W)|(?=\\W)|^|(?:\\n?$)|\\A|\\Z))(?:(?:((?:(?:(?:\\s*+(\\/\\*)((?:[^\\*]++|\\*+(?!\\/))*+(\\*\\/))\\s*+)+)|(?:\\s++)|(?<=\\W)|(?=\\W)|^|(?:\\n?$)|\\A|\\Z))((?]|\\n)(?!\\()|(?=\\\\end\\{(?:minted|cppcode)\\})", "beginCaptures": { "1": { "name": "meta.qualified_type.cpp", @@ -4718,24 +4412,7 @@ "include": "#scope_resolution_inner_generated" }, { - "begin": "<", - "end": ">|(?=\\\\end\\{(?:minted|cppcode)\\})", - "beginCaptures": { - "0": { - "name": "punctuation.section.angle-brackets.begin.template.call.cpp" - } - }, - "endCaptures": { - "0": { - "name": "punctuation.section.angle-brackets.end.template.call.cpp" - } - }, - "name": "meta.template.call.cpp", - "patterns": [ - { - "include": "#template_call_context" - } - ] + "include": "#template_call_range_helper" }, { "match": "(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*", @@ -4796,14 +4473,14 @@ "name": "entity.name.scope-resolution.type.cpp" }, { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, "12": { "patterns": [ { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, @@ -4955,6 +4632,41 @@ }, "5": { "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + "6": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "7": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "8": { + "name": "comment.block.cpp" + }, + "9": { + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + "10": { + "name": "storage.modifier.specifier.functional.post-parameters.$10.cpp" + }, + "11": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "12": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "13": { + "name": "comment.block.cpp" + }, + "14": { + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" } }, "patterns": [ @@ -4965,7 +4677,7 @@ }, "function_pointer_parameter": { "begin": "(\\s*+((?:(?:(?:\\[\\[.*?\\]\\]|__attribute(?:__)?\\s*\\(\\s*\\(.*?\\)\\s*\\))|__declspec\\(.*?\\))|alignas\\(.*?\\))(?!\\)))?((?:(?:(?:\\s*+(\\/\\*)((?:[^\\*]++|\\*+(?!\\/))*+(\\*\\/))\\s*+)+)|(?:\\s++)|(?<=\\W)|(?=\\W)|^|(?:\\n?$)|\\A|\\Z))(?:(?:(?:(?:unsigned)|(?:signed)|(?:short)|(?:long))|(?:(?:struct)|(?:class)|(?:union)|(?:enum)))((?:(?:(?:\\s*+(\\/\\*)((?:[^\\*]++|\\*+(?!\\/))*+(\\*\\/))\\s*+)+)|(?:\\s++)|(?<=\\W)|(?=\\W)|^|(?:\\n?$)|\\A|\\Z)))*(?:((?:::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|thread_local|dynamic_cast|synchronized|static_cast|const_cast|consteval|co_return|protected|constinit|constexpr|co_return|consteval|namespace|constexpr|constexpr|co_await|explicit|volatile|noexcept|co_yield|noexcept|noexcept|requires|typename|decltype|operator|template|continue|co_await|co_yield|volatile|register|restrict|reflexpr|mutable|alignof|include|private|defined|typedef|_Pragma|__asm__|concept|mutable|warning|default|virtual|alignas|public|sizeof|delete|not_eq|bitand|and_eq|xor_eq|typeid|switch|return|struct|static|extern|inline|friend|ifndef|define|pragma|export|import|module|catch|throw|const|or_eq|compl|while|ifdef|const|bitor|union|class|undef|error|break|using|endif|goto|line|enum|this|case|else|elif|else|not|try|for|asm|and|xor|new|do|if|or|if)\\b)(?|(?:(?:[^'\"<>\\/]|\\/[^*])++))*>)\\s*+)?::)*+)((?:(?:(?:\\s*+(\\/\\*)((?:[^\\*]++|\\*+(?!\\/))*+(\\*\\/))\\s*+)+)|(?:\\s++)|(?<=\\W)|(?=\\W)|^|(?:\\n?$)|\\A|\\Z)))?(?!(?:(?:transaction_safe_dynamic)|(?:__has_cpp_attribute)|(?:reinterpret_cast)|(?:transaction_safe)|(?:atomic_noexcept)|(?:atomic_commit)|(?:__has_include)|(?:atomic_cancel)|(?:synchronized)|(?:thread_local)|(?:dynamic_cast)|(?:static_cast)|(?:const_cast)|(?:constexpr)|(?:co_return)|(?:constinit)|(?:namespace)|(?:protected)|(?:consteval)|(?:constexpr)|(?:constexpr)|(?:co_return)|(?:consteval)|(?:co_await)|(?:continue)|(?:template)|(?:reflexpr)|(?:volatile)|(?:register)|(?:co_await)|(?:co_yield)|(?:restrict)|(?:noexcept)|(?:volatile)|(?:override)|(?:explicit)|(?:decltype)|(?:operator)|(?:noexcept)|(?:noexcept)|(?:typename)|(?:requires)|(?:co_yield)|(?:nullptr)|(?:alignof)|(?:alignas)|(?:default)|(?:mutable)|(?:virtual)|(?:mutable)|(?:private)|(?:include)|(?:warning)|(?:_Pragma)|(?:defined)|(?:typedef)|(?:__asm__)|(?:concept)|(?:define)|(?:module)|(?:sizeof)|(?:switch)|(?:delete)|(?:pragma)|(?:and_eq)|(?:inline)|(?:xor_eq)|(?:typeid)|(?:import)|(?:extern)|(?:public)|(?:bitand)|(?:static)|(?:export)|(?:return)|(?:friend)|(?:ifndef)|(?:not_eq)|(?:false)|(?:final)|(?:break)|(?:const)|(?:catch)|(?:endif)|(?:ifdef)|(?:undef)|(?:error)|(?:audit)|(?:while)|(?:using)|(?:axiom)|(?:or_eq)|(?:compl)|(?:throw)|(?:bitor)|(?:const)|(?:line)|(?:case)|(?:else)|(?:this)|(?:true)|(?:goto)|(?:else)|(?:NULL)|(?:elif)|(?:new)|(?:asm)|(?:xor)|(?:and)|(?:try)|(?:not)|(?:for)|(?:do)|(?:if)|(?:or)|(?:if))\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\b((?|(?:(?:[^'\"<>\\/]|\\/[^*])++))*>)?(?![\\w<:.]))(((?:(?:(?:\\s*+(\\/\\*)((?:[^\\*]++|\\*+(?!\\/))*+(\\*\\/))\\s*+)+)|(?:\\s++)|(?<=\\W)|(?=\\W)|^|(?:\\n?$)|\\A|\\Z))?(?:(?:&|\\*)((?:(?:(?:\\s*+(\\/\\*)((?:[^\\*]++|\\*+(?!\\/))*+(\\*\\/))\\s*+)+)|(?:\\s++)|(?<=\\W)|(?=\\W)|^|(?:\\n?$)|\\A|\\Z)))*(?:&|\\*))?((?:(?:(?:\\s*+(\\/\\*)((?:[^\\*]++|\\*+(?!\\/))*+(\\*\\/))\\s*+)+)|(?:\\s++)|(?<=\\W)|(?=\\W)|^|(?:\\n?$)|\\A|\\Z))(\\()(\\*)(?:\\s+)?((?:(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)?)(?:\\s+)?(?:(\\[)(\\w*)(\\])(?:\\s+)?)*(\\))(?:\\s+)?(\\()", - "end": "(\\))((?:(?:(?:\\s*+(\\/\\*)((?:[^\\*]++|\\*+(?!\\/))*+(\\*\\/))\\s*+)+)|(?:\\s++)|(?<=\\W)|(?=\\W)|^|(?:\\n?$)|\\A|\\Z))(?=[{=,);>]|\\n)(?!\\()|(?=\\\\end\\{(?:minted|cppcode)\\})", + "end": "(\\))((?:(?:(?:\\s*+(\\/\\*)((?:[^\\*]++|\\*+(?!\\/))*+(\\*\\/))\\s*+)+)|(?:\\s++)|(?<=\\W)|(?=\\W)|^|(?:\\n?$)|\\A|\\Z))(?:(?:((?:(?:(?:\\s*+(\\/\\*)((?:[^\\*]++|\\*+(?!\\/))*+(\\*\\/))\\s*+)+)|(?:\\s++)|(?<=\\W)|(?=\\W)|^|(?:\\n?$)|\\A|\\Z))((?]|\\n)(?!\\()|(?=\\\\end\\{(?:minted|cppcode)\\})", "beginCaptures": { "1": { "name": "meta.qualified_type.cpp", @@ -4997,24 +4709,7 @@ "include": "#scope_resolution_inner_generated" }, { - "begin": "<", - "end": ">|(?=\\\\end\\{(?:minted|cppcode)\\})", - "beginCaptures": { - "0": { - "name": "punctuation.section.angle-brackets.begin.template.call.cpp" - } - }, - "endCaptures": { - "0": { - "name": "punctuation.section.angle-brackets.end.template.call.cpp" - } - }, - "name": "meta.template.call.cpp", - "patterns": [ - { - "include": "#template_call_context" - } - ] + "include": "#template_call_range_helper" }, { "match": "(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*", @@ -5075,14 +4770,14 @@ "name": "entity.name.scope-resolution.type.cpp" }, { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, "12": { "patterns": [ { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, @@ -5234,6 +4929,41 @@ }, "5": { "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + "6": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "7": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "8": { + "name": "comment.block.cpp" + }, + "9": { + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + "10": { + "name": "storage.modifier.specifier.functional.post-parameters.$10.cpp" + }, + "11": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "12": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "13": { + "name": "comment.block.cpp" + }, + "14": { + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" } }, "patterns": [ @@ -5613,24 +5343,7 @@ "include": "#scope_resolution_inner_generated" }, { - "begin": "<", - "end": ">|(?=\\\\end\\{(?:minted|cppcode)\\})", - "beginCaptures": { - "0": { - "name": "punctuation.section.angle-brackets.begin.template.call.cpp" - } - }, - "endCaptures": { - "0": { - "name": "punctuation.section.angle-brackets.end.template.call.cpp" - } - }, - "name": "meta.template.call.cpp", - "patterns": [ - { - "include": "#template_call_context" - } - ] + "include": "#template_call_range_helper" }, { "match": "(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*", @@ -5709,14 +5422,14 @@ "name": "entity.name.scope-resolution.type.cpp" }, { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, "8": { "patterns": [ { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, @@ -5787,7 +5500,7 @@ "name": "invalid.illegal.unexpected.punctuation.definition.comment.end.cpp" }, "label": { - "match": "((?:((?:\\s*+\\/\\*(?:[^\\*]++|\\*+(?!\\/))*+\\*\\/\\s*+)+)|(?:\\s++)|(?<=\\W)|(?=\\W)|^|(?:\\n?$)|\\A|\\Z))((?|(?=\\\\end\\{(?:minted|cppcode)\\})", - "beginCaptures": { - "0": { - "name": "punctuation.section.angle-brackets.begin.template.call.cpp" - } - }, - "endCaptures": { - "0": { - "name": "punctuation.section.angle-brackets.end.template.call.cpp" - } - }, - "name": "meta.template.call.cpp", - "patterns": [ - { - "include": "#template_call_context" - } - ] + "include": "#template_call_range_helper" }, { "match": "(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*", @@ -6872,14 +6568,14 @@ "name": "entity.name.scope-resolution.type.cpp" }, { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, "24": { "patterns": [ { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, @@ -7107,24 +6803,7 @@ "include": "#scope_resolution_inner_generated" }, { - "begin": "<", - "end": ">|(?=\\\\end\\{(?:minted|cppcode)\\})", - "beginCaptures": { - "0": { - "name": "punctuation.section.angle-brackets.begin.template.call.cpp" - } - }, - "endCaptures": { - "0": { - "name": "punctuation.section.angle-brackets.end.template.call.cpp" - } - }, - "name": "meta.template.call.cpp", - "patterns": [ - { - "include": "#template_call_context" - } - ] + "include": "#template_call_range_helper" }, { "match": "(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*", @@ -7185,14 +6864,14 @@ "name": "entity.name.scope-resolution.type.cpp" }, { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, "24": { "patterns": [ { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, @@ -7655,24 +7334,7 @@ "include": "#scope_resolution_inner_generated" }, { - "begin": "<", - "end": ">|(?=\\\\end\\{(?:minted|cppcode)\\})", - "beginCaptures": { - "0": { - "name": "punctuation.section.angle-brackets.begin.template.call.cpp" - } - }, - "endCaptures": { - "0": { - "name": "punctuation.section.angle-brackets.end.template.call.cpp" - } - }, - "name": "meta.template.call.cpp", - "patterns": [ - { - "include": "#template_call_context" - } - ] + "include": "#template_call_range_helper" }, { "match": "(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*", @@ -7733,14 +7395,14 @@ "name": "entity.name.scope-resolution.type.cpp" }, { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, "16": { "patterns": [ { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, @@ -7890,14 +7552,14 @@ "name": "entity.name.scope-resolution.operator.cpp" }, { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, "46": { "patterns": [ { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, @@ -7951,14 +7613,14 @@ "name": "entity.name.scope-resolution.operator-overload.cpp" }, { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, "59": { "patterns": [ { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, @@ -8111,7 +7773,7 @@ "include": "#ever_present_context" }, { - "include": "#template_call_range" + "include": "#template_call_range_helper" }, { "begin": "\\(", @@ -9611,7 +9273,7 @@ "include": "#scope_resolution_parameter_inner_generated" }, { - "match": "(?:(?:struct)|(?:class)|(?:union)|(?:enum))", + "match": "(?|(?:(?:[^'\"<>\\/]|\\/[^*])++))*>)\\s*+)?::)*+)((?:((?:\\s*+\\/\\*(?:[^\\*]++|\\*+(?!\\/))*+\\*\\/\\s*+)+)|(?:\\s++)|(?<=\\W)|(?=\\W)|^|(?:\\n?$)|\\A|\\Z)))?(?!(?:(?:transaction_safe_dynamic)|(?:__has_cpp_attribute)|(?:reinterpret_cast)|(?:transaction_safe)|(?:atomic_noexcept)|(?:atomic_commit)|(?:__has_include)|(?:atomic_cancel)|(?:synchronized)|(?:thread_local)|(?:dynamic_cast)|(?:static_cast)|(?:const_cast)|(?:constexpr)|(?:co_return)|(?:constinit)|(?:namespace)|(?:protected)|(?:consteval)|(?:constexpr)|(?:constexpr)|(?:co_return)|(?:consteval)|(?:co_await)|(?:continue)|(?:template)|(?:reflexpr)|(?:volatile)|(?:register)|(?:co_await)|(?:co_yield)|(?:restrict)|(?:noexcept)|(?:volatile)|(?:override)|(?:explicit)|(?:decltype)|(?:operator)|(?:noexcept)|(?:noexcept)|(?:typename)|(?:requires)|(?:co_yield)|(?:nullptr)|(?:alignof)|(?:alignas)|(?:default)|(?:mutable)|(?:virtual)|(?:mutable)|(?:private)|(?:include)|(?:warning)|(?:_Pragma)|(?:defined)|(?:typedef)|(?:__asm__)|(?:concept)|(?:define)|(?:module)|(?:sizeof)|(?:switch)|(?:delete)|(?:pragma)|(?:and_eq)|(?:inline)|(?:xor_eq)|(?:typeid)|(?:import)|(?:extern)|(?:public)|(?:bitand)|(?:static)|(?:export)|(?:return)|(?:friend)|(?:ifndef)|(?:not_eq)|(?:false)|(?:final)|(?:break)|(?:const)|(?:catch)|(?:endif)|(?:ifdef)|(?:undef)|(?:error)|(?:audit)|(?:while)|(?:using)|(?:axiom)|(?:or_eq)|(?:compl)|(?:throw)|(?:bitor)|(?:const)|(?:line)|(?:case)|(?:else)|(?:this)|(?:true)|(?:goto)|(?:else)|(?:NULL)|(?:elif)|(?:new)|(?:asm)|(?:xor)|(?:and)|(?:try)|(?:not)|(?:for)|(?:do)|(?:if)|(?:or)|(?:if))\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\b((?|(?:(?:[^'\"<>\\/]|\\/[^*])++))*>)?(?![\\w<:.])", + "preprocessor_number_literal": { + "match": "(?|(?=\\\\end\\{(?:minted|cppcode)\\})", - "beginCaptures": { - "0": { - "name": "punctuation.section.angle-brackets.begin.template.call.cpp" - } - }, - "endCaptures": { - "0": { - "name": "punctuation.section.angle-brackets.end.template.call.cpp" - } - }, - "name": "meta.template.call.cpp", + "begin": "(?=.)", + "end": "$|(?=\\\\end\\{(?:minted|cppcode)\\})", + "beginCaptures": {}, + "endCaptures": {}, "patterns": [ { - "include": "#template_call_context" - } - ] - }, - { - "match": "(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*", - "name": "entity.name.type.cpp" - } - ] - }, - "1": { - "patterns": [ - { - "include": "#attributes_context" - }, - { - "include": "#number_literal" - } - ] - }, - "2": { - "patterns": [ - { - "include": "#inline_comment" - } - ] - }, - "3": { - "patterns": [ - { - "match": "\\s*+(\\/\\*)((?:[^\\*]++|\\*+(?!\\/))*+(\\*\\/))\\s*+", - "captures": { - "1": { - "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" - }, - "2": { - "name": "comment.block.cpp" + "match": "(\\G0[xX])([0-9a-fA-F](?:[0-9a-fA-F]|((?<=[0-9a-fA-F])'(?=[0-9a-fA-F])))*)?((?:(?<=[0-9a-fA-F])\\.|\\.(?=[0-9a-fA-F])))([0-9a-fA-F](?:[0-9a-fA-F]|((?<=[0-9a-fA-F])'(?=[0-9a-fA-F])))*)?(?:(?|(?:(?:[^'\"<>\\/]|\\/[^*])++))*>)\\s*+)?::)*+)((?:((?:\\s*+\\/\\*(?:[^\\*]++|\\*+(?!\\/))*+\\*\\/\\s*+)+)|(?:\\s++)|(?<=\\W)|(?=\\W)|^|(?:\\n?$)|\\A|\\Z)))?(?!(?:(?:transaction_safe_dynamic)|(?:__has_cpp_attribute)|(?:reinterpret_cast)|(?:transaction_safe)|(?:atomic_noexcept)|(?:atomic_commit)|(?:__has_include)|(?:atomic_cancel)|(?:synchronized)|(?:thread_local)|(?:dynamic_cast)|(?:static_cast)|(?:const_cast)|(?:constexpr)|(?:co_return)|(?:constinit)|(?:namespace)|(?:protected)|(?:consteval)|(?:constexpr)|(?:constexpr)|(?:co_return)|(?:consteval)|(?:co_await)|(?:continue)|(?:template)|(?:reflexpr)|(?:volatile)|(?:register)|(?:co_await)|(?:co_yield)|(?:restrict)|(?:noexcept)|(?:volatile)|(?:override)|(?:explicit)|(?:decltype)|(?:operator)|(?:noexcept)|(?:noexcept)|(?:typename)|(?:requires)|(?:co_yield)|(?:nullptr)|(?:alignof)|(?:alignas)|(?:default)|(?:mutable)|(?:virtual)|(?:mutable)|(?:private)|(?:include)|(?:warning)|(?:_Pragma)|(?:defined)|(?:typedef)|(?:__asm__)|(?:concept)|(?:define)|(?:module)|(?:sizeof)|(?:switch)|(?:delete)|(?:pragma)|(?:and_eq)|(?:inline)|(?:xor_eq)|(?:typeid)|(?:import)|(?:extern)|(?:public)|(?:bitand)|(?:static)|(?:export)|(?:return)|(?:friend)|(?:ifndef)|(?:not_eq)|(?:false)|(?:final)|(?:break)|(?:const)|(?:catch)|(?:endif)|(?:ifdef)|(?:undef)|(?:error)|(?:audit)|(?:while)|(?:using)|(?:axiom)|(?:or_eq)|(?:compl)|(?:throw)|(?:bitor)|(?:const)|(?:line)|(?:case)|(?:else)|(?:this)|(?:true)|(?:goto)|(?:else)|(?:NULL)|(?:elif)|(?:new)|(?:asm)|(?:xor)|(?:and)|(?:try)|(?:not)|(?:for)|(?:do)|(?:if)|(?:or)|(?:if))\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\b((?|(?:(?:[^'\"<>\\/]|\\/[^*])++))*>)?(?![\\w<:.])", + "captures": { + "0": { + "patterns": [ + { + "match": "::", + "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.cpp" + }, + { + "match": "(?|(?=\\\\end\\{(?:minted|cppcode)\\})", - "beginCaptures": { - "0": { - "name": "punctuation.section.angle-brackets.begin.template.call.cpp" - } - }, - "endCaptures": { - "0": { - "name": "punctuation.section.angle-brackets.end.template.call.cpp" - } - }, - "name": "meta.template.call.cpp", - "patterns": [ - { - "include": "#template_call_context" - } - ] + "include": "#template_call_range_helper" }, { "match": "(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*", @@ -11737,14 +11620,14 @@ "name": "entity.name.scope-resolution.type.cpp" }, { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, "21": { "patterns": [ { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, @@ -11940,24 +11823,7 @@ "include": "#scope_resolution_inner_generated" }, { - "begin": "<", - "end": ">|(?=\\\\end\\{(?:minted|cppcode)\\})", - "beginCaptures": { - "0": { - "name": "punctuation.section.angle-brackets.begin.template.call.cpp" - } - }, - "endCaptures": { - "0": { - "name": "punctuation.section.angle-brackets.end.template.call.cpp" - } - }, - "name": "meta.template.call.cpp", - "patterns": [ - { - "include": "#template_call_context" - } - ] + "include": "#template_call_range_helper" }, { "match": "(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*", @@ -12018,14 +11884,14 @@ "name": "entity.name.scope-resolution.type.cpp" }, { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, "21": { "patterns": [ { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, @@ -12249,7 +12115,7 @@ "2": { "patterns": [ { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] } @@ -12271,7 +12137,7 @@ "2": { "patterns": [ { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] } @@ -12293,7 +12159,7 @@ "3": { "patterns": [ { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, @@ -12305,7 +12171,7 @@ "name": "meta.template.call.cpp", "patterns": [ { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, @@ -12340,7 +12206,7 @@ "2": { "patterns": [ { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] } @@ -12362,7 +12228,7 @@ "3": { "patterns": [ { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, @@ -12374,7 +12240,7 @@ "name": "meta.template.call.cpp", "patterns": [ { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, @@ -12409,7 +12275,7 @@ "2": { "patterns": [ { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] } @@ -12431,7 +12297,7 @@ "3": { "patterns": [ { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, @@ -12443,7 +12309,7 @@ "name": "meta.template.call.cpp", "patterns": [ { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, @@ -12478,7 +12344,7 @@ "3": { "patterns": [ { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, @@ -12490,7 +12356,7 @@ "name": "meta.template.call.cpp", "patterns": [ { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, @@ -12525,7 +12391,7 @@ "2": { "patterns": [ { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] } @@ -12547,7 +12413,7 @@ "3": { "patterns": [ { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, @@ -12559,7 +12425,7 @@ "name": "meta.template.call.cpp", "patterns": [ { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, @@ -12594,7 +12460,7 @@ "2": { "patterns": [ { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] } @@ -12616,7 +12482,7 @@ "3": { "patterns": [ { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, @@ -12628,7 +12494,7 @@ "name": "meta.template.call.cpp", "patterns": [ { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, @@ -12663,7 +12529,7 @@ "2": { "patterns": [ { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] } @@ -12685,7 +12551,7 @@ "3": { "patterns": [ { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, @@ -12697,7 +12563,7 @@ "name": "meta.template.call.cpp", "patterns": [ { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, @@ -12732,7 +12598,7 @@ "2": { "patterns": [ { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] } @@ -12754,7 +12620,7 @@ "3": { "patterns": [ { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, @@ -12766,7 +12632,7 @@ "name": "meta.template.call.cpp", "patterns": [ { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, @@ -12801,7 +12667,7 @@ "2": { "patterns": [ { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] } @@ -12823,7 +12689,7 @@ "3": { "patterns": [ { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, @@ -12835,7 +12701,7 @@ "name": "meta.template.call.cpp", "patterns": [ { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, @@ -12870,7 +12736,7 @@ "2": { "patterns": [ { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] } @@ -12892,7 +12758,7 @@ "3": { "patterns": [ { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, @@ -12904,7 +12770,7 @@ "name": "meta.template.call.cpp", "patterns": [ { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, @@ -12960,24 +12826,7 @@ "include": "#scope_resolution_inner_generated" }, { - "begin": "<", - "end": ">|(?=\\\\end\\{(?:minted|cppcode)\\})", - "beginCaptures": { - "0": { - "name": "punctuation.section.angle-brackets.begin.template.call.cpp" - } - }, - "endCaptures": { - "0": { - "name": "punctuation.section.angle-brackets.end.template.call.cpp" - } - }, - "name": "meta.template.call.cpp", - "patterns": [ - { - "include": "#template_call_context" - } - ] + "include": "#template_call_range_helper" }, { "match": "(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*", @@ -13056,14 +12905,14 @@ "name": "entity.name.scope-resolution.type.cpp" }, { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, "8": { "patterns": [ { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, @@ -14310,8 +14159,8 @@ ] }, { - "begin": "((?:[uUL]8?)?R)\\\"(?:[pP]?(?:sql|SQL)|d[dm]l)\\(", - "end": "\\)(?:[pP]?(?:sql|SQL)|d[dm]l)\\\"|(?=\\\\end\\{(?:minted|cppcode)\\})", + "begin": "((?:[uUL]8?)?R)\\\"\\(", + "end": "\\)\\\"|(?=\\\\end\\{(?:minted|cppcode)\\})", "beginCaptures": { "0": { "name": "punctuation.definition.string.begin.cpp" @@ -14325,18 +14174,16 @@ "name": "punctuation.definition.string.end.cpp" } }, - "name": "meta.string.quoted.double.raw.sql.cpp", + "name": "string.quoted.double.raw.cpp", "patterns": [ - { - "include": "source.sql" - } + {} ] }, { "begin": "((?:u|u8|U|L)?R)\"(?:([^ ()\\\\\\t]{0,16})|([^ ()\\\\\\t]*))\\(", "beginCaptures": { "0": { - "name": "punctuation.definition.string.begin" + "name": "punctuation.definition.string.$2.begin" }, "1": { "name": "meta.encoding" @@ -14345,25 +14192,29 @@ "name": "invalid.illegal.delimiter-too-long" } }, - "end": "(\\)\\2(\\3)\")(?:((?:[a-zA-Z]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)|(_(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))?|(?=\\\\end\\{(?:minted|cppcode)\\})", + "end": "(\\)(\\2)(\\3)\")(?:((?:[a-zA-Z]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)|(_(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*))?|(?=\\\\end\\{(?:minted|cppcode)\\})", "endCaptures": { "1": { - "name": "punctuation.definition.string.end" + "name": "punctuation.definition.string.$2.end" }, - "2": { + "3": { "name": "invalid.illegal.delimiter-too-long" }, - "3": { + "4": { "name": "keyword.other.suffix.literal.user-defined.reserved.string.cpp" }, - "4": { + "5": { "name": "keyword.other.suffix.literal.user-defined.string.cpp" } }, - "name": "string.quoted.double.raw" + "name": "string.quoted.double.raw.$2" } ] }, + "string_escaped_char": { + "match": "(?x)\\\\ (\n\\\\\t\t\t |\n[abefnprtv'\"?] |\n[0-3][0-7]{,2}\t |\n[4-7]\\d?\t\t|\nx[a-fA-F0-9]{,2} |\nu[a-fA-F0-9]{,4} |\nU[a-fA-F0-9]{,8} )", + "name": "constant.character.escape" + }, "string_escapes_context_c": { "patterns": [ { @@ -14575,7 +14426,7 @@ "include": "#inheritance_context" }, { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, @@ -14886,134 +14737,743 @@ { "include": "#switch_conditional_parentheses" }, - { - "include": "$self" - } - ] - }, - { - "begin": "(?<=\\{|<%|\\?\\?<)", - "end": "\\}|%>|\\?\\?>|(?=\\\\end\\{(?:minted|cppcode)\\})", - "beginCaptures": {}, - "endCaptures": { - "0": { - "name": "punctuation.section.block.end.bracket.curly.switch.cpp" - } - }, - "name": "meta.body.switch.cpp", - "patterns": [ - { - "include": "#default_statement" + { + "include": "$self" + } + ] + }, + { + "begin": "(?<=\\{|<%|\\?\\?<)", + "end": "\\}|%>|\\?\\?>|(?=\\\\end\\{(?:minted|cppcode)\\})", + "beginCaptures": {}, + "endCaptures": { + "0": { + "name": "punctuation.section.block.end.bracket.curly.switch.cpp" + } + }, + "name": "meta.body.switch.cpp", + "patterns": [ + { + "include": "#default_statement" + }, + { + "include": "#case_statement" + }, + { + "include": "$self" + } + ] + }, + { + "begin": "(?<=\\}|%>|\\?\\?>)[\\s]*", + "end": "[\\s]*(?=;)|(?=\\\\end\\{(?:minted|cppcode)\\})", + "beginCaptures": {}, + "endCaptures": {}, + "name": "meta.tail.switch.cpp", + "patterns": [ + { + "include": "$self" + } + ] + } + ] + }, + "template_argument_defaulted": { + "match": "(?<=<|,)(?:\\s+)?((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s+((?:(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)?)(?:\\s+)?(\\=)", + "captures": { + "1": { + "name": "storage.type.template.argument.$1.cpp" + }, + "2": { + "name": "entity.name.type.template.cpp" + }, + "3": { + "name": "keyword.operator.assignment.cpp" + } + } + }, + "template_call_context": { + "patterns": [ + { + "include": "#ever_present_context" + }, + { + "include": "#template_call_range_helper" + }, + { + "include": "#storage_types" + }, + { + "include": "#language_constants" + }, + { + "include": "#scope_resolution_template_call_inner_generated" + }, + { + "include": "#operators" + }, + { + "include": "#number_literal" + }, + { + "include": "#string_context" + }, + { + "include": "#comma_in_template_argument" + }, + { + "include": "#qualified_type" + } + ] + }, + "template_call_innards": { + "match": "((?|(?:(?:[^'\"<>\\/]|\\/[^*])++))*>)\\s*+", + "captures": { + "0": { + "patterns": [ + { + "include": "#template_call_range_helper" + } + ] + }, + "2": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "3": { + "name": "comment.block.cpp" + }, + "4": { + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + } + }, + "name": "meta.template.call.cpp" + }, + "template_call_range": { + "begin": "<", + "end": ">|(?=\\\\end\\{(?:minted|cppcode)\\})", + "beginCaptures": { + "0": { + "name": "punctuation.section.angle-brackets.begin.template.call.cpp" + } + }, + "endCaptures": { + "0": { + "name": "punctuation.section.angle-brackets.end.template.call.cpp" + } + }, + "name": "meta.template.call.cpp", + "patterns": [ + { + "include": "#template_call_context" + } + ] + }, + "template_call_range_helper": { + "patterns": [ + { + "match": "\\b((?|\\?\\?>)[\\s]*", - "end": "[\\s]*(?=;)|(?=\\\\end\\{(?:minted|cppcode)\\})", - "beginCaptures": {}, - "endCaptures": {}, - "name": "meta.tail.switch.cpp", - "patterns": [ - { - "include": "$self" + "4": { + "name": "keyword.operator.comparison.cpp" } - ] - } - ] - }, - "template_argument_defaulted": { - "match": "(?<=<|,)(?:\\s+)?((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s+((?:(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)?)(?:\\s+)?(\\=)", - "captures": { - "1": { - "name": "storage.type.template.argument.$1.cpp" - }, - "2": { - "name": "entity.name.type.template.cpp" - }, - "3": { - "name": "keyword.operator.assignment.cpp" - } - } - }, - "template_call_context": { - "patterns": [ - { - "include": "#ever_present_context" + } }, { "include": "#template_call_range" - }, - { - "include": "#storage_types" - }, - { - "include": "#language_constants" - }, - { - "include": "#scope_resolution_template_call_inner_generated" - }, - { - "include": "#operators" - }, - { - "include": "#number_literal" - }, - { - "include": "#string_context" - }, - { - "include": "#comma_in_template_argument" - }, - { - "include": "#qualified_type" - } - ] - }, - "template_call_innards": { - "match": "((?|(?:(?:[^'\"<>\\/]|\\/[^*])++))*>)\\s*+", - "captures": { - "0": { - "patterns": [ - { - "include": "#template_call_range" - } - ] - }, - "2": { - "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" - }, - "3": { - "name": "comment.block.cpp" - }, - "4": { - "name": "comment.block.cpp punctuation.definition.comment.end.cpp" - } - }, - "name": "meta.template.call.cpp" - }, - "template_call_range": { - "begin": "<", - "end": ">|(?=\\\\end\\{(?:minted|cppcode)\\})", - "beginCaptures": { - "0": { - "name": "punctuation.section.angle-brackets.begin.template.call.cpp" - } - }, - "endCaptures": { - "0": { - "name": "punctuation.section.angle-brackets.end.template.call.cpp" - } - }, - "name": "meta.template.call.cpp", - "patterns": [ - { - "include": "#template_call_context" } ] }, @@ -15400,24 +15860,7 @@ "include": "#scope_resolution_inner_generated" }, { - "begin": "<", - "end": ">|(?=\\\\end\\{(?:minted|cppcode)\\})", - "beginCaptures": { - "0": { - "name": "punctuation.section.angle-brackets.begin.template.call.cpp" - } - }, - "endCaptures": { - "0": { - "name": "punctuation.section.angle-brackets.end.template.call.cpp" - } - }, - "name": "meta.template.call.cpp", - "patterns": [ - { - "include": "#template_call_context" - } - ] + "include": "#template_call_range_helper" }, { "match": "(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*", @@ -15496,14 +15939,14 @@ "name": "entity.name.scope-resolution.type.cpp" }, { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, "15": { "patterns": [ { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, @@ -15906,7 +16349,7 @@ "include": "#inheritance_context" }, { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, @@ -16065,7 +16508,7 @@ "patterns": [ { "begin": "(\\s*+((?:(?:(?:\\[\\[.*?\\]\\]|__attribute(?:__)?\\s*\\(\\s*\\(.*?\\)\\s*\\))|__declspec\\(.*?\\))|alignas\\(.*?\\))(?!\\)))?((?:(?:(?:\\s*+(\\/\\*)((?:[^\\*]++|\\*+(?!\\/))*+(\\*\\/))\\s*+)+)|(?:\\s++)|(?<=\\W)|(?=\\W)|^|(?:\\n?$)|\\A|\\Z))(?:(?:(?:(?:unsigned)|(?:signed)|(?:short)|(?:long))|(?:(?:struct)|(?:class)|(?:union)|(?:enum)))((?:(?:(?:\\s*+(\\/\\*)((?:[^\\*]++|\\*+(?!\\/))*+(\\*\\/))\\s*+)+)|(?:\\s++)|(?<=\\W)|(?=\\W)|^|(?:\\n?$)|\\A|\\Z)))*(?:((?:::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|thread_local|dynamic_cast|synchronized|static_cast|const_cast|consteval|co_return|protected|constinit|constexpr|co_return|consteval|namespace|constexpr|constexpr|co_await|explicit|volatile|noexcept|co_yield|noexcept|noexcept|requires|typename|decltype|operator|template|continue|co_await|co_yield|volatile|register|restrict|reflexpr|mutable|alignof|include|private|defined|typedef|_Pragma|__asm__|concept|mutable|warning|default|virtual|alignas|public|sizeof|delete|not_eq|bitand|and_eq|xor_eq|typeid|switch|return|struct|static|extern|inline|friend|ifndef|define|pragma|export|import|module|catch|throw|const|or_eq|compl|while|ifdef|const|bitor|union|class|undef|error|break|using|endif|goto|line|enum|this|case|else|elif|else|not|try|for|asm|and|xor|new|do|if|or|if)\\b)(?|(?:(?:[^'\"<>\\/]|\\/[^*])++))*>)\\s*+)?::)*+)((?:(?:(?:\\s*+(\\/\\*)((?:[^\\*]++|\\*+(?!\\/))*+(\\*\\/))\\s*+)+)|(?:\\s++)|(?<=\\W)|(?=\\W)|^|(?:\\n?$)|\\A|\\Z)))?(?!(?:(?:transaction_safe_dynamic)|(?:__has_cpp_attribute)|(?:reinterpret_cast)|(?:transaction_safe)|(?:atomic_noexcept)|(?:atomic_commit)|(?:__has_include)|(?:atomic_cancel)|(?:synchronized)|(?:thread_local)|(?:dynamic_cast)|(?:static_cast)|(?:const_cast)|(?:constexpr)|(?:co_return)|(?:constinit)|(?:namespace)|(?:protected)|(?:consteval)|(?:constexpr)|(?:constexpr)|(?:co_return)|(?:consteval)|(?:co_await)|(?:continue)|(?:template)|(?:reflexpr)|(?:volatile)|(?:register)|(?:co_await)|(?:co_yield)|(?:restrict)|(?:noexcept)|(?:volatile)|(?:override)|(?:explicit)|(?:decltype)|(?:operator)|(?:noexcept)|(?:noexcept)|(?:typename)|(?:requires)|(?:co_yield)|(?:nullptr)|(?:alignof)|(?:alignas)|(?:default)|(?:mutable)|(?:virtual)|(?:mutable)|(?:private)|(?:include)|(?:warning)|(?:_Pragma)|(?:defined)|(?:typedef)|(?:__asm__)|(?:concept)|(?:define)|(?:module)|(?:sizeof)|(?:switch)|(?:delete)|(?:pragma)|(?:and_eq)|(?:inline)|(?:xor_eq)|(?:typeid)|(?:import)|(?:extern)|(?:public)|(?:bitand)|(?:static)|(?:export)|(?:return)|(?:friend)|(?:ifndef)|(?:not_eq)|(?:false)|(?:final)|(?:break)|(?:const)|(?:catch)|(?:endif)|(?:ifdef)|(?:undef)|(?:error)|(?:audit)|(?:while)|(?:using)|(?:axiom)|(?:or_eq)|(?:compl)|(?:throw)|(?:bitor)|(?:const)|(?:line)|(?:case)|(?:else)|(?:this)|(?:true)|(?:goto)|(?:else)|(?:NULL)|(?:elif)|(?:new)|(?:asm)|(?:xor)|(?:and)|(?:try)|(?:not)|(?:for)|(?:do)|(?:if)|(?:or)|(?:if))\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\b((?|(?:(?:[^'\"<>\\/]|\\/[^*])++))*>)?(?![\\w<:.]))(((?:(?:(?:\\s*+(\\/\\*)((?:[^\\*]++|\\*+(?!\\/))*+(\\*\\/))\\s*+)+)|(?:\\s++)|(?<=\\W)|(?=\\W)|^|(?:\\n?$)|\\A|\\Z))?(?:(?:&|\\*)((?:(?:(?:\\s*+(\\/\\*)((?:[^\\*]++|\\*+(?!\\/))*+(\\*\\/))\\s*+)+)|(?:\\s++)|(?<=\\W)|(?=\\W)|^|(?:\\n?$)|\\A|\\Z)))*(?:&|\\*))?((?:(?:(?:\\s*+(\\/\\*)((?:[^\\*]++|\\*+(?!\\/))*+(\\*\\/))\\s*+)+)|(?:\\s++)|(?<=\\W)|(?=\\W)|^|(?:\\n?$)|\\A|\\Z))(\\()(\\*)(?:\\s+)?((?:(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)?)(?:\\s+)?(?:(\\[)(\\w*)(\\])(?:\\s+)?)*(\\))(?:\\s+)?(\\()", - "end": "(\\))((?:(?:(?:\\s*+(\\/\\*)((?:[^\\*]++|\\*+(?!\\/))*+(\\*\\/))\\s*+)+)|(?:\\s++)|(?<=\\W)|(?=\\W)|^|(?:\\n?$)|\\A|\\Z))(?=[{=,);>]|\\n)(?!\\()|(?=\\\\end\\{(?:minted|cppcode)\\})", + "end": "(\\))((?:(?:(?:\\s*+(\\/\\*)((?:[^\\*]++|\\*+(?!\\/))*+(\\*\\/))\\s*+)+)|(?:\\s++)|(?<=\\W)|(?=\\W)|^|(?:\\n?$)|\\A|\\Z))(?:(?:((?:(?:(?:\\s*+(\\/\\*)((?:[^\\*]++|\\*+(?!\\/))*+(\\*\\/))\\s*+)+)|(?:\\s++)|(?<=\\W)|(?=\\W)|^|(?:\\n?$)|\\A|\\Z))((?]|\\n)(?!\\()|(?=\\\\end\\{(?:minted|cppcode)\\})", "beginCaptures": { "1": { "name": "meta.qualified_type.cpp", @@ -16097,24 +16540,7 @@ "include": "#scope_resolution_inner_generated" }, { - "begin": "<", - "end": ">|(?=\\\\end\\{(?:minted|cppcode)\\})", - "beginCaptures": { - "0": { - "name": "punctuation.section.angle-brackets.begin.template.call.cpp" - } - }, - "endCaptures": { - "0": { - "name": "punctuation.section.angle-brackets.end.template.call.cpp" - } - }, - "name": "meta.template.call.cpp", - "patterns": [ - { - "include": "#template_call_context" - } - ] + "include": "#template_call_range_helper" }, { "match": "(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*", @@ -16175,14 +16601,14 @@ "name": "entity.name.scope-resolution.type.cpp" }, { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, "12": { "patterns": [ { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, @@ -16334,6 +16760,41 @@ }, "5": { "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + "6": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "7": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "8": { + "name": "comment.block.cpp" + }, + "9": { + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + "10": { + "name": "storage.modifier.specifier.functional.post-parameters.$10.cpp" + }, + "11": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "12": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "13": { + "name": "comment.block.cpp" + }, + "14": { + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" } }, "patterns": [ @@ -16549,7 +17010,7 @@ "include": "#inheritance_context" }, { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, @@ -16901,7 +17362,7 @@ "include": "#inheritance_context" }, { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, @@ -17173,24 +17634,7 @@ "include": "#scope_resolution_inner_generated" }, { - "begin": "<", - "end": ">|(?=\\\\end\\{(?:minted|cppcode)\\})", - "beginCaptures": { - "0": { - "name": "punctuation.section.angle-brackets.begin.template.call.cpp" - } - }, - "endCaptures": { - "0": { - "name": "punctuation.section.angle-brackets.end.template.call.cpp" - } - }, - "name": "meta.template.call.cpp", - "patterns": [ - { - "include": "#template_call_context" - } - ] + "include": "#template_call_range_helper" }, { "match": "(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*", @@ -17269,14 +17713,14 @@ "name": "entity.name.scope-resolution.type.cpp" }, { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, "13": { "patterns": [ { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, @@ -17569,7 +18013,7 @@ "include": "#inheritance_context" }, { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, @@ -17828,7 +18272,7 @@ "5": { "patterns": [ { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, @@ -17931,24 +18375,7 @@ "include": "#scope_resolution_inner_generated" }, { - "begin": "<", - "end": ">|(?=\\\\end\\{(?:minted|cppcode)\\})", - "beginCaptures": { - "0": { - "name": "punctuation.section.angle-brackets.begin.template.call.cpp" - } - }, - "endCaptures": { - "0": { - "name": "punctuation.section.angle-brackets.end.template.call.cpp" - } - }, - "name": "meta.template.call.cpp", - "patterns": [ - { - "include": "#template_call_context" - } - ] + "include": "#template_call_range_helper" }, { "match": "(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*", @@ -18027,14 +18454,14 @@ "name": "entity.name.scope-resolution.type.cpp" }, { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, "12": { "patterns": [ { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, @@ -18296,24 +18723,7 @@ "include": "#scope_resolution_inner_generated" }, { - "begin": "<", - "end": ">|(?=\\\\end\\{(?:minted|cppcode)\\})", - "beginCaptures": { - "0": { - "name": "punctuation.section.angle-brackets.begin.template.call.cpp" - } - }, - "endCaptures": { - "0": { - "name": "punctuation.section.angle-brackets.end.template.call.cpp" - } - }, - "name": "meta.template.call.cpp", - "patterns": [ - { - "include": "#template_call_context" - } - ] + "include": "#template_call_range_helper" }, { "match": "(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*", @@ -18392,14 +18802,14 @@ "name": "entity.name.scope-resolution.type.cpp" }, { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, "12": { "patterns": [ { - "include": "#template_call_range" + "include": "#template_call_range_helper" } ] }, diff --git a/extensions/less/cgmanifest.json b/extensions/less/cgmanifest.json index 663e1cc4dafde..caf908bbcc05d 100644 --- a/extensions/less/cgmanifest.json +++ b/extensions/less/cgmanifest.json @@ -6,7 +6,7 @@ "git": { "name": "language-less", "repositoryUrl": "/~https://github.com/radium-v/Better-Less", - "commitHash": "05de79f600227201e35f07a49f07acce80e49dbf" + "commitHash": "24047277622c245dbe9309f0004d0ccb8f02636f" } }, "license": "MIT", diff --git a/extensions/less/syntaxes/less.tmLanguage.json b/extensions/less/syntaxes/less.tmLanguage.json index 3d2c6bdaeb018..2acac68838544 100644 --- a/extensions/less/syntaxes/less.tmLanguage.json +++ b/extensions/less/syntaxes/less.tmLanguage.json @@ -4,7 +4,7 @@ "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "/~https://github.com/radium-v/Better-Less/commit/05de79f600227201e35f07a49f07acce80e49dbf", + "version": "/~https://github.com/radium-v/Better-Less/commit/24047277622c245dbe9309f0004d0ccb8f02636f", "name": "Less", "scopeName": "source.css.less", "patterns": [ @@ -3966,7 +3966,7 @@ ] }, { - "begin": "\\bfilter\\b", + "begin": "\\b(?:backdrop-)?filter\\b", "beginCaptures": { "0": { "name": "support.type.property-name.less" diff --git a/extensions/lua/cgmanifest.json b/extensions/lua/cgmanifest.json index 50afc15d1cf83..f35219d5a615c 100644 --- a/extensions/lua/cgmanifest.json +++ b/extensions/lua/cgmanifest.json @@ -6,7 +6,7 @@ "git": { "name": "sumneko/lua.tmbundle", "repositoryUrl": "/~https://github.com/sumneko/lua.tmbundle", - "commitHash": "94ce82cc4d45f82641a5252d7a7fd9e28c875adc" + "commitHash": "1483add845ebfb3e1e631fe372603e5fed2cdd42" } }, "licenseDetail": [ diff --git a/extensions/lua/syntaxes/lua.tmLanguage.json b/extensions/lua/syntaxes/lua.tmLanguage.json index e578b8846cbab..61875d06cf85b 100644 --- a/extensions/lua/syntaxes/lua.tmLanguage.json +++ b/extensions/lua/syntaxes/lua.tmLanguage.json @@ -4,7 +4,7 @@ "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "/~https://github.com/sumneko/lua.tmbundle/commit/94ce82cc4d45f82641a5252d7a7fd9e28c875adc", + "version": "/~https://github.com/sumneko/lua.tmbundle/commit/1483add845ebfb3e1e631fe372603e5fed2cdd42", "name": "Lua", "scopeName": "source.lua", "patterns": [ @@ -141,8 +141,8 @@ { "match": "<\\s*(const|close)\\s*>", "captures": { - "1": { - "name": "string.tag.lua" + "0": { + "name": "storage.type.attribute.lua" } } }, @@ -155,7 +155,7 @@ "name": "keyword.control.lua" }, { - "match": "\\b(local|global)\\b", + "match": "\\b(local)\\b", "name": "keyword.local.lua" }, { @@ -363,7 +363,7 @@ "name": "punctuation.definition.comment.begin.lua" } }, - "end": "\\]\\1\\]", + "end": "(--)?\\]\\1\\]", "endCaptures": { "0": { "name": "punctuation.definition.comment.end.lua" @@ -383,7 +383,7 @@ "name": "punctuation.definition.comment.begin.lua" } }, - "end": "\\]\\1\\]", + "end": "(--)?\\]\\1\\]", "endCaptures": { "0": { "name": "punctuation.definition.comment.end.lua" @@ -472,7 +472,7 @@ "emmydoc": { "patterns": [ { - "begin": "(?<=---[ \\t]*)@class", + "begin": "(?<=---)[ \\t]*@class", "beginCaptures": { "0": { "name": "storage.type.annotation.lua" @@ -491,7 +491,7 @@ ] }, { - "begin": "(?<=---[ \\t]*)@enum", + "begin": "(?<=---)[ \\t]*@enum", "beginCaptures": { "0": { "name": "storage.type.annotation.lua" @@ -511,7 +511,7 @@ ] }, { - "begin": "(?<=---[ \\t]*)@type", + "begin": "(?<=---)[ \\t]*@type", "beginCaptures": { "0": { "name": "storage.type.annotation.lua" @@ -525,7 +525,7 @@ ] }, { - "begin": "(?<=---[ \\t]*)@alias", + "begin": "(?<=---)[ \\t]*@alias", "beginCaptures": { "0": { "name": "storage.type.annotation.lua" @@ -550,7 +550,7 @@ ] }, { - "begin": "(?<=---[ \\t]*)(@operator)\\s*(\\b[a-z]+)?", + "begin": "(?<=---)[ \\t]*(@operator)\\s*(\\b[a-z]+)?", "beginCaptures": { "1": { "name": "storage.type.annotation.lua" @@ -567,7 +567,7 @@ ] }, { - "begin": "(?<=---[ \\t]*)@cast", + "begin": "(?<=---)[ \\t]*@cast", "beginCaptures": { "0": { "name": "storage.type.annotation.lua" @@ -596,7 +596,7 @@ ] }, { - "begin": "(?<=---[ \\t]*)@param", + "begin": "(?<=---)[ \\t]*@param", "beginCaptures": { "0": { "name": "storage.type.annotation.lua" @@ -624,7 +624,7 @@ ] }, { - "begin": "(?<=---[ \\t]*)@return", + "begin": "(?<=---)[ \\t]*@return", "beginCaptures": { "0": { "name": "storage.type.annotation.lua" @@ -642,7 +642,7 @@ ] }, { - "begin": "(?<=---[ \\t]*)@field", + "begin": "(?<=---)[ \\t]*@field", "beginCaptures": { "0": { "name": "storage.type.annotation.lua" @@ -677,7 +677,7 @@ ] }, { - "begin": "(?<=---[ \\t]*)@generic", + "begin": "(?<=---)[ \\t]*@generic", "beginCaptures": { "0": { "name": "storage.type.annotation.lua" @@ -711,7 +711,7 @@ ] }, { - "begin": "(?<=---[ \\t]*)@vararg", + "begin": "(?<=---)[ \\t]*@vararg", "beginCaptures": { "0": { "name": "storage.type.annotation.lua" @@ -725,7 +725,7 @@ ] }, { - "begin": "(?<=---[ \\t]*)@overload", + "begin": "(?<=---)[ \\t]*@overload", "beginCaptures": { "0": { "name": "storage.type.annotation.lua" @@ -739,7 +739,7 @@ ] }, { - "begin": "(?<=---[ \\t]*)@deprecated", + "begin": "(?<=---)[ \\t]*@deprecated", "beginCaptures": { "0": { "name": "storage.type.annotation.lua" @@ -748,7 +748,7 @@ "end": "(?=[\\n@#])" }, { - "begin": "(?<=---[ \\t]*)@meta", + "begin": "(?<=---)[ \\t]*@meta", "beginCaptures": { "0": { "name": "storage.type.annotation.lua" @@ -757,7 +757,7 @@ "end": "(?=[\\n@#])" }, { - "begin": "(?<=---[ \\t]*)@private", + "begin": "(?<=---)[ \\t]*@private", "beginCaptures": { "0": { "name": "storage.type.annotation.lua" @@ -766,7 +766,7 @@ "end": "(?=[\\n@#])" }, { - "begin": "(?<=---[ \\t]*)@protected", + "begin": "(?<=---)[ \\t]*@protected", "beginCaptures": { "0": { "name": "storage.type.annotation.lua" @@ -775,7 +775,7 @@ "end": "(?=[\\n@#])" }, { - "begin": "(?<=---[ \\t]*)@package", + "begin": "(?<=---)[ \\t]*@package", "beginCaptures": { "0": { "name": "storage.type.annotation.lua" @@ -784,7 +784,7 @@ "end": "(?=[\\n@#])" }, { - "begin": "(?<=---[ \\t]*)@version", + "begin": "(?<=---)[ \\t]*@version", "beginCaptures": { "0": { "name": "storage.type.annotation.lua" @@ -803,7 +803,7 @@ ] }, { - "begin": "(?<=---[ \\t]*)@see", + "begin": "(?<=---)[ \\t]*@see", "beginCaptures": { "0": { "name": "storage.type.annotation.lua" @@ -822,7 +822,7 @@ ] }, { - "begin": "(?<=---[ \\t]*)@diagnostic", + "begin": "(?<=---)[ \\t]*@diagnostic", "beginCaptures": { "0": { "name": "storage.type.annotation.lua" @@ -855,7 +855,7 @@ ] }, { - "begin": "(?<=---[ \\t]*)@module", + "begin": "(?<=---)[ \\t]*@module", "beginCaptures": { "0": { "name": "storage.type.annotation.lua" @@ -869,7 +869,7 @@ ] }, { - "match": "(?<=---[ \\t]*)@(async|nodiscard)", + "match": "(?<=---)[ \\t]*@(async|nodiscard)", "name": "storage.type.annotation.lua" }, { diff --git a/extensions/razor/cgmanifest.json b/extensions/razor/cgmanifest.json index d3685974bdb62..b8b0e5dae4f77 100644 --- a/extensions/razor/cgmanifest.json +++ b/extensions/razor/cgmanifest.json @@ -6,7 +6,7 @@ "git": { "name": "dotnet/razor", "repositoryUrl": "/~https://github.com/dotnet/razor", - "commitHash": "f01e110af179981942987384d2b5d4e489eab014" + "commitHash": "39159764277f3c80a786d8872eba7730da3d7ef0" } }, "license": "MIT", diff --git a/extensions/razor/syntaxes/cshtml.tmLanguage.json b/extensions/razor/syntaxes/cshtml.tmLanguage.json index 389a6daf249e7..71055e66e102a 100644 --- a/extensions/razor/syntaxes/cshtml.tmLanguage.json +++ b/extensions/razor/syntaxes/cshtml.tmLanguage.json @@ -4,9 +4,31 @@ "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "/~https://github.com/dotnet/razor/commit/f01e110af179981942987384d2b5d4e489eab014", + "version": "/~https://github.com/dotnet/razor/commit/39159764277f3c80a786d8872eba7730da3d7ef0", "name": "ASP.NET Razor", "scopeName": "text.html.cshtml", + "injections": { + "string.quoted.double.html": { + "patterns": [ + { + "include": "#explicit-razor-expression" + }, + { + "include": "#implicit-expression" + } + ] + }, + "string.quoted.single.html": { + "patterns": [ + { + "include": "#explicit-razor-expression" + }, + { + "include": "#implicit-expression" + } + ] + } + }, "patterns": [ { "include": "#razor-control-structures" diff --git a/extensions/shellscript/cgmanifest.json b/extensions/shellscript/cgmanifest.json index 01ceff5f55aaa..48f939ecc4570 100644 --- a/extensions/shellscript/cgmanifest.json +++ b/extensions/shellscript/cgmanifest.json @@ -6,11 +6,11 @@ "git": { "name": "jeff-hykin/better-shell-syntax", "repositoryUrl": "/~https://github.com/jeff-hykin/better-shell-syntax", - "commitHash": "21748db7c7fd6ccd660c5bc770212836e58385ae" + "commitHash": "6d0bc37a6b8023a5fddf75bd2b4eb1e1f962e4c2" } }, "license": "MIT", - "version": "1.8.3" + "version": "1.8.7" } ], "version": 1 diff --git a/extensions/shellscript/syntaxes/shell-unix-bash.tmLanguage.json b/extensions/shellscript/syntaxes/shell-unix-bash.tmLanguage.json index 28492442703b5..7aae970d227cd 100644 --- a/extensions/shellscript/syntaxes/shell-unix-bash.tmLanguage.json +++ b/extensions/shellscript/syntaxes/shell-unix-bash.tmLanguage.json @@ -4,7 +4,7 @@ "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "/~https://github.com/jeff-hykin/better-shell-syntax/commit/21748db7c7fd6ccd660c5bc770212836e58385ae", + "version": "/~https://github.com/jeff-hykin/better-shell-syntax/commit/6d0bc37a6b8023a5fddf75bd2b4eb1e1f962e4c2", "name": "Shell Script", "scopeName": "source.shell", "patterns": [ @@ -14,7 +14,7 @@ ], "repository": { "alias_statement": { - "begin": "(?:(alias)(?:[ \\t]*+)((?:(?:((?\\(\\)\\$`\\\\\"\\|]+)(?!>))", + "match": "(?:[ \\t]*+)((?:[^ \t\n>&;<>\\(\\)\\$`\\\\\"'<\\|]+)(?!>))", "captures": { "1": { "name": "string.unquoted.argument.shell", @@ -296,7 +296,7 @@ ] }, "basic_command_name": { - "match": "(?:(?:(?!(?:!|&|\\||\\(|\\)|\\{|\\[|<|>|#|\\n|$|;|[ \\t]))(?!nocorrect |nocorrect\t|nocorrect$|readonly |readonly\t|readonly$|function |function\t|function$|foreach |foreach\t|foreach$|coproc |coproc\t|coproc$|logout |logout\t|logout$|export |export\t|export$|select |select\t|select$|repeat |repeat\t|repeat$|pushd |pushd\t|pushd$|until |until\t|until$|while |while\t|while$|local |local\t|local$|case |case\t|case$|done |done\t|done$|elif |elif\t|elif$|else |else\t|else$|esac |esac\t|esac$|popd |popd\t|popd$|then |then\t|then$|time |time\t|time$|for |for\t|for$|end |end\t|end$|fi |fi\t|fi$|do |do\t|do$|in |in\t|in$|if |if\t|if$))(?:((?<=^|;|&|[ \\t])(?:readonly|declare|typeset|export|local)(?=[ \\t]|;|&|$))|((?!\"|'|\\\\\\n?$)(?:[^!'\" \\t\\n\\r]+?)))(?:(?= |\\t)|(?:(?=;|\\||&|\\n|\\)|\\`|\\{|\\}|[ \\t]*#|\\])(?|#|\\n|$|;|[ \\t]))(?!nocorrect |nocorrect\t|nocorrect$|readonly |readonly\t|readonly$|function |function\t|function$|foreach |foreach\t|foreach$|coproc |coproc\t|coproc$|logout |logout\t|logout$|export |export\t|export$|select |select\t|select$|repeat |repeat\t|repeat$|pushd |pushd\t|pushd$|until |until\t|until$|while |while\t|while$|local |local\t|local$|case |case\t|case$|done |done\t|done$|elif |elif\t|elif$|else |else\t|else$|esac |esac\t|esac$|popd |popd\t|popd$|then |then\t|then$|time |time\t|time$|for |for\t|for$|end |end\t|end$|fi |fi\t|fi$|do |do\t|do$|in |in\t|in$|if |if\t|if$))(?:((?<=^|;|&|[ \\t])(?:readonly|declare|typeset|export|local)(?=[ \\t]|;|&|$))|((?!\"|'|\\\\\\n?$)(?:[^!'\"<> \\t\\n\\r]+?)))(?:(?= |\\t)|(?:(?=;|\\||&|\\n|\\)|\\`|\\{|\\}|[ \\t]*#|\\])(?]+))", "captures": { "1": { "name": "entity.name.function.call.shell entity.name.command.shell" @@ -564,6 +572,9 @@ }, { "include": "#string" + }, + { + "include": "#heredoc" } ] }, @@ -867,7 +878,7 @@ }, "endCaptures": { "0": { - "name": "punctuation.definition.string.heredoc.delimiter.shell" + "name": "punctuation.definition.string.heredoc.$0.shell" } }, "contentName": "string.quoted.heredoc.indent.$3", @@ -1500,6 +1511,30 @@ } ] }, + "math_operators": { + "patterns": [ + { + "match": "\\+{1,2}|-{1,2}|!|~|\\*{1,2}|/|%|<[<=]?|>[>=]?|==|!=|^|\\|{1,2}|&{1,2}|\\?|\\:|,|=|[*/%+\\-&^|]=|<<=|>>=", + "name": "keyword.operator.arithmetic.shell" + }, + { + "match": "0[xX][0-9A-Fa-f]+", + "name": "constant.numeric.hex.shell" + }, + { + "match": "0\\d+", + "name": "constant.numeric.octal.shell" + }, + { + "match": "\\d{1,2}#[0-9a-zA-Z@_]+", + "name": "constant.numeric.other.shell" + }, + { + "match": "\\d+", + "name": "constant.numeric.integer.shell" + } + ] + }, "misc_ranges": { "patterns": [ { @@ -1912,7 +1947,7 @@ ] }, "redirect_fix": { - "match": "(?:(>>?)(?:[ \\t]*+)([^ \t\n'&;<>\\(\\)\\$`\\\\\"\\|]+))", + "match": "(?:(>>?)(?:[ \\t]*+)([^ \t\n>&;<>\\(\\)\\$`\\\\\"'<\\|]+))", "captures": { "1": { "name": "keyword.operator.redirect.shell" @@ -1996,7 +2031,7 @@ } }, "simple_unquoted": { - "match": "[^ \\t\\n'&;<>\\(\\)\\$`\\\\\"\\|]", + "match": "[^ \\t\\n>&;<>\\(\\)\\$`\\\\\"'<\\|]", "name": "string.unquoted.shell" }, "special_expansion": { @@ -2135,6 +2170,9 @@ { "include": "#for_statement" }, + { + "include": "#while_statement" + }, { "include": "#function_definition" }, @@ -2275,6 +2313,41 @@ } } ] + }, + "while_statement": { + "patterns": [ + { + "begin": "(\\bwhile\\b)", + "end": "(?=;|\\||&|\\n|\\)|\\`|\\{|\\}|[ \\t]*#|\\])(? Date: Fri, 26 Apr 2024 05:37:50 -0700 Subject: [PATCH 014/104] Create stripAnsiEscapeSequences helper Fixes #211444 --- src/vs/base/common/ansi.ts | 19 +++++++++++++++ src/vs/base/test/common/ansi.test.ts | 24 +++++++++++++++++++ .../contrib/remote/browser/urlFinder.ts | 4 ++-- 3 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 src/vs/base/common/ansi.ts create mode 100644 src/vs/base/test/common/ansi.test.ts diff --git a/src/vs/base/common/ansi.ts b/src/vs/base/common/ansi.ts new file mode 100644 index 0000000000000..2ef437651c647 --- /dev/null +++ b/src/vs/base/common/ansi.ts @@ -0,0 +1,19 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Lazy } from 'vs/base/common/lazy'; + +const ansiEscapeSequenceRegex = new Lazy(() => /(?:\u001B|\u009B)[\[\]()#;?]*(?:(?:(?:[a-zA-Z0-9]*(?:;[a-zA-Z0-9]*)*)?\u0007)|(?:(?:\d{1,4}(?:;\d{0,4})*)?[0-9A-PR-TZcf-ntqry=><~]))/g); + +/** + * Strips ANSI escape sequences from a string. + * @param data The data to strip the ANSI escape sequences from. + * + * @example + * stripAnsiEscapeSequences('\u001b[31mHello, World!\u001b[0m'); // 'Hello, World!' + */ +export function stripAnsiEscapeSequences(data: string): string { + return data.replace(ansiEscapeSequenceRegex.value, ''); +} diff --git a/src/vs/base/test/common/ansi.test.ts b/src/vs/base/test/common/ansi.test.ts new file mode 100644 index 0000000000000..c1d19c98f6018 --- /dev/null +++ b/src/vs/base/test/common/ansi.test.ts @@ -0,0 +1,24 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { strictEqual } from 'assert'; +import { stripAnsiEscapeSequences } from 'vs/base/common/ansi'; +import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils'; + +suite('ansi', () => { + ensureNoDisposablesAreLeakedInTestSuite(); + + suite('stripAnsiEscapeSequences', () => { + test('should strip simple SGR escape sequences', () => { + strictEqual(stripAnsiEscapeSequences('\u001b[31mHello, World!\u001b[0m'), 'Hello, World!'); + }); + test('should strip complex SGR escape sequences', () => { + strictEqual(stripAnsiEscapeSequences('\u001b[38;2;255;82;197;48;2;155;106;0mHello, World!\u001b[0m'), 'Hello, World!'); + }); + test('should strip ED, EL escape sequences', () => { + strictEqual(stripAnsiEscapeSequences('\u001b[KHello, World!\r\n\u001b[2J'), 'Hello, World!\r\n'); + }); + }); +}); diff --git a/src/vs/workbench/contrib/remote/browser/urlFinder.ts b/src/vs/workbench/contrib/remote/browser/urlFinder.ts index 7fed46eb3a704..db63ef81eff01 100644 --- a/src/vs/workbench/contrib/remote/browser/urlFinder.ts +++ b/src/vs/workbench/contrib/remote/browser/urlFinder.ts @@ -7,9 +7,9 @@ import { ITerminalInstance, ITerminalService } from 'vs/workbench/contrib/termin import { Emitter } from 'vs/base/common/event'; import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; import { IDebugService, IDebugSession, IReplElement } from 'vs/workbench/contrib/debug/common/debug'; +import { stripAnsiEscapeSequences } from 'vs/base/common/ansi'; export class UrlFinder extends Disposable { - private static readonly terminalCodesRegex = /(?:\u001B|\u009B)[\[\]()#;?]*(?:(?:(?:[a-zA-Z0-9]*(?:;[a-zA-Z0-9]*)*)?\u0007)|(?:(?:\d{1,4}(?:;\d{0,4})*)?[0-9A-PR-TZcf-ntqry=><~]))/g; /** * Local server url pattern matching following urls: * http://localhost:3000/ - commonly used across multiple frameworks @@ -99,7 +99,7 @@ export class UrlFinder extends Disposable { private processData(data: string) { // strip ANSI terminal codes - data = data.replace(UrlFinder.terminalCodesRegex, ''); + data = stripAnsiEscapeSequences(data); const urlMatches = data.match(UrlFinder.localUrlRegex) || []; if (urlMatches && urlMatches.length > 0) { urlMatches.forEach((match) => { From cdaa40be28254eda70d4eb79c11245c24f178841 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Fri, 26 Apr 2024 05:46:28 -0700 Subject: [PATCH 015/104] Add helper for stripping PS1-style prompts Fixes #211445 --- src/vs/base/common/ansi.ts | 18 +++++++++++++++++- src/vs/base/test/common/ansi.test.ts | 11 ++++++++++- .../common/xterm/shellIntegrationAddon.ts | 8 ++------ 3 files changed, 29 insertions(+), 8 deletions(-) diff --git a/src/vs/base/common/ansi.ts b/src/vs/base/common/ansi.ts index 2ef437651c647..7a5d93bbfb827 100644 --- a/src/vs/base/common/ansi.ts +++ b/src/vs/base/common/ansi.ts @@ -6,14 +6,30 @@ import { Lazy } from 'vs/base/common/lazy'; const ansiEscapeSequenceRegex = new Lazy(() => /(?:\u001B|\u009B)[\[\]()#;?]*(?:(?:(?:[a-zA-Z0-9]*(?:;[a-zA-Z0-9]*)*)?\u0007)|(?:(?:\d{1,4}(?:;\d{0,4})*)?[0-9A-PR-TZcf-ntqry=><~]))/g); +const promptNonPrintableCharactersRegex = new Lazy(() => /\\\[.*?\\\]/g); /** * Strips ANSI escape sequences from a string. * @param data The data to strip the ANSI escape sequences from. * * @example - * stripAnsiEscapeSequences('\u001b[31mHello, World!\u001b[0m'); // 'Hello, World!' + * stripAnsiEscapeSequences('\u001b[31mHello, World!\u001b[0m'); + * // 'Hello, World!' */ export function stripAnsiEscapeSequences(data: string): string { return data.replace(ansiEscapeSequenceRegex.value, ''); } + +/** + * Strips ANSI escape sequences from a UNIX-style prompt string (eg. `$PS1`). + * @param data The data to strip the ANSI escape sequences from. + * + * @example + * stripAnsiEscapeSequencesFromPrompt('\n\\[\u001b[01;34m\\]\\w\\[\u001b[00m\\]\n\\[\u001b[1;32m\\]> \\[\u001b[0m\\]'); + * // '\n\\w\n> ' + */ +export function stripAnsiEscapeSequencesFromPrompt(data: string): string { + return (data + .replace(ansiEscapeSequenceRegex.value, '') + .replace(promptNonPrintableCharactersRegex.value, '')); +} diff --git a/src/vs/base/test/common/ansi.test.ts b/src/vs/base/test/common/ansi.test.ts index c1d19c98f6018..0bdf32840cf21 100644 --- a/src/vs/base/test/common/ansi.test.ts +++ b/src/vs/base/test/common/ansi.test.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { strictEqual } from 'assert'; -import { stripAnsiEscapeSequences } from 'vs/base/common/ansi'; +import { stripAnsiEscapeSequences, stripAnsiEscapeSequencesFromPrompt } from 'vs/base/common/ansi'; import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils'; suite('ansi', () => { @@ -21,4 +21,13 @@ suite('ansi', () => { strictEqual(stripAnsiEscapeSequences('\u001b[KHello, World!\r\n\u001b[2J'), 'Hello, World!\r\n'); }); }); + + suite('stripAnsiEscapeSequencesFromPrompt', () => { + test('should strip simple SGR escape sequences', () => { + strictEqual(stripAnsiEscapeSequences('\u001b[31m$ \u001b[0m'), '$ '); + }); + test('should strip \[ and \] chars and their contents', () => { + strictEqual(stripAnsiEscapeSequencesFromPrompt('\n\\[\u001b[01;34m\\]\\w\\[\u001b[00m\\]\n\\[\u001b[1;32m\\]> \\[\u001b[0m\\]'), '\n\\w\n> '); + }); + }); }); diff --git a/src/vs/platform/terminal/common/xterm/shellIntegrationAddon.ts b/src/vs/platform/terminal/common/xterm/shellIntegrationAddon.ts index 249e67ab44dd2..3404e18e5284a 100644 --- a/src/vs/platform/terminal/common/xterm/shellIntegrationAddon.ts +++ b/src/vs/platform/terminal/common/xterm/shellIntegrationAddon.ts @@ -21,6 +21,7 @@ import { BufferMarkCapability } from 'vs/platform/terminal/common/capabilities/b import type { ITerminalAddon, Terminal } from '@xterm/headless'; import { URI } from 'vs/base/common/uri'; import { sanitizeCwd } from 'vs/platform/terminal/common/terminalEnvironment'; +import { stripAnsiEscapeSequencesFromPrompt } from 'vs/base/common/ansi'; /** @@ -382,12 +383,7 @@ export class ShellIntegrationAddon extends Disposable implements IShellIntegrati } switch (key) { case 'ContinuationPrompt': { - // Exclude escape sequences and values between \[ and \] - const sanitizedValue = (value - .replace(/\x1b\[[0-9;]*m/g, '') - .replace(/\\\[.*?\\\]/g, '') - ); - this._updateContinuationPrompt(sanitizedValue); + this._updateContinuationPrompt(stripAnsiEscapeSequencesFromPrompt(value)); return true; } case 'Cwd': { From 6cdd364d9336216c2a9c8d98a35d30275aa0a87d Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Fri, 26 Apr 2024 05:54:23 -0700 Subject: [PATCH 016/104] Remove canvas renderer Fixes #209276 --- package.json | 1 - remote/package.json | 1 - remote/web/package.json | 1 - remote/web/yarn.lock | 5 -- remote/yarn.lock | 5 -- scripts/xterm-update.js | 1 - .../terminal/browser/xterm/xtermTerminal.ts | 61 ++----------------- .../contrib/terminal/common/terminal.ts | 2 +- .../terminal/common/terminalConfiguration.ts | 3 +- yarn.lock | 5 -- 10 files changed, 6 insertions(+), 79 deletions(-) diff --git a/package.json b/package.json index 1f5a34f8e87da..4d9098974c0ba 100644 --- a/package.json +++ b/package.json @@ -81,7 +81,6 @@ "@vscode/windows-mutex": "^0.5.0", "@vscode/windows-process-tree": "^0.6.0", "@vscode/windows-registry": "^1.1.0", - "@xterm/addon-canvas": "0.8.0-beta.17", "@xterm/addon-image": "0.9.0-beta.17", "@xterm/addon-search": "0.16.0-beta.17", "@xterm/addon-serialize": "0.14.0-beta.17", diff --git a/remote/package.json b/remote/package.json index 0bec8279e6612..b65d496611349 100644 --- a/remote/package.json +++ b/remote/package.json @@ -13,7 +13,6 @@ "@vscode/vscode-languagedetection": "1.0.21", "@vscode/windows-process-tree": "^0.6.0", "@vscode/windows-registry": "^1.1.0", - "@xterm/addon-canvas": "0.8.0-beta.17", "@xterm/addon-image": "0.9.0-beta.17", "@xterm/addon-search": "0.16.0-beta.17", "@xterm/addon-serialize": "0.14.0-beta.17", diff --git a/remote/web/package.json b/remote/web/package.json index 326cf519ada67..88588ecb87999 100644 --- a/remote/web/package.json +++ b/remote/web/package.json @@ -7,7 +7,6 @@ "@microsoft/1ds-post-js": "^3.2.13", "@vscode/iconv-lite-umd": "0.7.0", "@vscode/vscode-languagedetection": "1.0.21", - "@xterm/addon-canvas": "0.8.0-beta.17", "@xterm/addon-image": "0.9.0-beta.17", "@xterm/addon-search": "0.16.0-beta.17", "@xterm/addon-serialize": "0.14.0-beta.17", diff --git a/remote/web/yarn.lock b/remote/web/yarn.lock index ed86d85e39cf6..cb7ee772ee54f 100644 --- a/remote/web/yarn.lock +++ b/remote/web/yarn.lock @@ -48,11 +48,6 @@ resolved "https://registry.yarnpkg.com/@vscode/vscode-languagedetection/-/vscode-languagedetection-1.0.21.tgz#89b48f293f6aa3341bb888c1118d16ff13b032d3" integrity sha512-zSUH9HYCw5qsCtd7b31yqkpaCU6jhtkKLkvOOA8yTrIRfBSOFb8PPhgmMicD7B/m+t4PwOJXzU1XDtrM9Fd3/g== -"@xterm/addon-canvas@0.8.0-beta.17": - version "0.8.0-beta.17" - resolved "https://registry.yarnpkg.com/@xterm/addon-canvas/-/addon-canvas-0.8.0-beta.17.tgz#309630c738aa2e44742cdce5ee88fb8079fa652c" - integrity sha512-1km1RE02rxdbJWp1sev6Um6T/4tWlpEhJ88OP7xwfUFuedhFEby0JXmKzP7qB0cFzEvFTCq1bOAHSA3DX8vlFQ== - "@xterm/addon-image@0.9.0-beta.17": version "0.9.0-beta.17" resolved "https://registry.yarnpkg.com/@xterm/addon-image/-/addon-image-0.9.0-beta.17.tgz#343d0665a6060d4f893b4f2d32de6ccbbd00bb63" diff --git a/remote/yarn.lock b/remote/yarn.lock index 66fe13a5c4c51..683dabccbf3da 100644 --- a/remote/yarn.lock +++ b/remote/yarn.lock @@ -114,11 +114,6 @@ resolved "https://registry.yarnpkg.com/@vscode/windows-registry/-/windows-registry-1.1.0.tgz#03dace7c29c46f658588b9885b9580e453ad21f9" integrity sha512-5AZzuWJpGscyiMOed0IuyEwt6iKmV5Us7zuwCDCFYMIq7tsvooO9BUiciywsvuthGz6UG4LSpeDeCxvgMVhnIw== -"@xterm/addon-canvas@0.8.0-beta.17": - version "0.8.0-beta.17" - resolved "https://registry.yarnpkg.com/@xterm/addon-canvas/-/addon-canvas-0.8.0-beta.17.tgz#309630c738aa2e44742cdce5ee88fb8079fa652c" - integrity sha512-1km1RE02rxdbJWp1sev6Um6T/4tWlpEhJ88OP7xwfUFuedhFEby0JXmKzP7qB0cFzEvFTCq1bOAHSA3DX8vlFQ== - "@xterm/addon-image@0.9.0-beta.17": version "0.9.0-beta.17" resolved "https://registry.yarnpkg.com/@xterm/addon-image/-/addon-image-0.9.0-beta.17.tgz#343d0665a6060d4f893b4f2d32de6ccbbd00bb63" diff --git a/scripts/xterm-update.js b/scripts/xterm-update.js index 747d7af3ea802..851b296af62c5 100644 --- a/scripts/xterm-update.js +++ b/scripts/xterm-update.js @@ -8,7 +8,6 @@ const path = require('path'); const moduleNames = [ '@xterm/xterm', - '@xterm/addon-canvas', '@xterm/addon-image', '@xterm/addon-search', '@xterm/addon-serialize', diff --git a/src/vs/workbench/contrib/terminal/browser/xterm/xtermTerminal.ts b/src/vs/workbench/contrib/terminal/browser/xterm/xtermTerminal.ts index 7aeb0a5941744..67136657ac519 100644 --- a/src/vs/workbench/contrib/terminal/browser/xterm/xtermTerminal.ts +++ b/src/vs/workbench/contrib/terminal/browser/xterm/xtermTerminal.ts @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ import type { IBuffer, ITerminalOptions, ITheme, Terminal as RawXtermTerminal, LogLevel as XtermLogLevel } from '@xterm/xterm'; -import type { CanvasAddon as CanvasAddonType } from '@xterm/addon-canvas'; import type { ISearchOptions, SearchAddon as SearchAddonType } from '@xterm/addon-search'; import type { Unicode11Addon as Unicode11AddonType } from '@xterm/addon-unicode11'; import type { WebglAddon as WebglAddonType } from '@xterm/addon-webgl'; @@ -45,7 +44,6 @@ const enum RenderConstants { SmoothScrollDuration = 125 } -let CanvasAddon: typeof CanvasAddonType; let ImageAddon: typeof ImageAddonType; let SearchAddon: typeof SearchAddonType; let SerializeAddon: typeof SerializeAddonType; @@ -121,7 +119,6 @@ export class XtermTerminal extends Disposable implements IXtermTerminal, IDetach private _decorationAddon: DecorationAddon; // Optional addons - private _canvasAddon?: CanvasAddonType; private _searchAddon?: SearchAddonType; private _unicode11Addon?: Unicode11AddonType; private _webglAddon?: WebglAddonType; @@ -136,7 +133,7 @@ export class XtermTerminal extends Disposable implements IXtermTerminal, IDetach get findResult(): { resultIndex: number; resultCount: number } | undefined { return this._lastFindResult; } get isStdinDisabled(): boolean { return !!this.raw.options.disableStdin; } - get isGpuAccelerated(): boolean { return !!(this._canvasAddon || this._webglAddon); } + get isGpuAccelerated(): boolean { return !!this._webglAddon; } private readonly _onDidRequestRunCommand = this._register(new Emitter<{ command: ITerminalCommand; copyAsHtml?: boolean; noNewLine?: boolean }>()); readonly onDidRequestRunCommand = this._onDidRequestRunCommand.event; @@ -159,7 +156,7 @@ export class XtermTerminal extends Disposable implements IXtermTerminal, IDetach get shellIntegration(): IShellIntegration { return this._shellIntegrationAddon; } get textureAtlas(): Promise | undefined { - const canvas = this._webglAddon?.textureAtlas || this._canvasAddon?.textureAtlas; + const canvas = this._webglAddon?.textureAtlas; if (!canvas) { return undefined; } @@ -332,8 +329,6 @@ export class XtermTerminal extends Disposable implements IXtermTerminal, IDetach if (options.enableGpu) { if (this._shouldLoadWebgl()) { this._enableWebglRenderer(); - } else if (this._shouldLoadCanvas()) { - this._enableCanvasRenderer(); } } @@ -406,11 +401,6 @@ export class XtermTerminal extends Disposable implements IXtermTerminal, IDetach this._enableWebglRenderer(); } else { this._disposeOfWebglRenderer(); - if (this._shouldLoadCanvas()) { - this._enableCanvasRenderer(); - } else { - this._disposeOfCanvasRenderer(); - } } } } @@ -423,10 +413,6 @@ export class XtermTerminal extends Disposable implements IXtermTerminal, IDetach return (this._terminalConfigurationService.config.gpuAcceleration === 'auto' && XtermTerminal._suggestedRendererType === undefined) || this._terminalConfigurationService.config.gpuAcceleration === 'on'; } - private _shouldLoadCanvas(): boolean { - return this._terminalConfigurationService.config.gpuAcceleration === 'canvas'; - } - forceRedraw() { this.raw.clearTextureAtlas(); } @@ -680,7 +666,6 @@ export class XtermTerminal extends Disposable implements IXtermTerminal, IDetach const Addon = await this._getWebglAddonConstructor(); this._webglAddon = new Addon(); - this._disposeOfCanvasRenderer(); try { this.raw.loadAddon(this._webglAddon); this._logService.trace('Webgl was loaded'); @@ -706,38 +691,10 @@ export class XtermTerminal extends Disposable implements IXtermTerminal, IDetach this._disposeOfWebglRenderer(); } - /** - * @deprecated This will be removed in the future, see /~https://github.com/microsoft/vscode/issues/209276 - */ - private async _enableCanvasRenderer(): Promise { - if (!this.raw.element || this._canvasAddon) { - return; - } - const Addon = await this._getCanvasAddonConstructor(); - this._canvasAddon = new Addon(); - this._disposeOfWebglRenderer(); - try { - this.raw.loadAddon(this._canvasAddon); - this._logService.trace('Canvas renderer was loaded'); - } catch (e) { - this._logService.warn(`Canvas renderer could not be loaded, falling back to dom renderer`, e); - XtermTerminal._suggestedRendererType = 'dom'; - this._disposeOfCanvasRenderer(); - } - this._refreshImageAddon(); - } - - protected async _getCanvasAddonConstructor(): Promise { - if (!CanvasAddon) { - CanvasAddon = (await importAMDNodeModule('@xterm/addon-canvas', 'lib/xterm-addon-canvas.js')).CanvasAddon; - } - return CanvasAddon; - } - @debounce(100) private async _refreshImageAddon(): Promise { - // Only allow the image addon when a canvas is being used to avoid possible GPU issues - if (this._terminalConfigurationService.config.enableImages && (this._canvasAddon || this._webglAddon)) { + // Only allow the image addon when webgl is being used to avoid possible GPU issues + if (this._terminalConfigurationService.config.enableImages && this._webglAddon) { if (!this._imageAddon) { const AddonCtor = await this._getImageAddonConstructor(); this._imageAddon = new AddonCtor(); @@ -788,16 +745,6 @@ export class XtermTerminal extends Disposable implements IXtermTerminal, IDetach return SerializeAddon; } - private _disposeOfCanvasRenderer(): void { - try { - this._canvasAddon?.dispose(); - } catch { - // ignore - } - this._canvasAddon = undefined; - this._refreshImageAddon(); - } - private _disposeOfWebglRenderer(): void { try { this._webglAddon?.dispose(); diff --git a/src/vs/workbench/contrib/terminal/common/terminal.ts b/src/vs/workbench/contrib/terminal/common/terminal.ts index a2c8e2a804ed1..3117275afe9d4 100644 --- a/src/vs/workbench/contrib/terminal/common/terminal.ts +++ b/src/vs/workbench/contrib/terminal/common/terminal.ts @@ -135,7 +135,7 @@ export interface ITerminalConfiguration { altClickMovesCursor: boolean; macOptionIsMeta: boolean; macOptionClickForcesSelection: boolean; - gpuAcceleration: 'auto' | 'on' | 'canvas' | 'off'; + gpuAcceleration: 'auto' | 'on' | 'off'; rightClickBehavior: 'default' | 'copyPaste' | 'paste' | 'selectWord' | 'nothing'; middleClickBehavior: 'default' | 'paste'; cursorBlinking: boolean; diff --git a/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts b/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts index cb9ab6eb930f4..a3e4b8dd2de0a 100644 --- a/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts +++ b/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts @@ -296,12 +296,11 @@ const terminalConfiguration: IConfigurationNode = { }, [TerminalSettingId.GpuAcceleration]: { type: 'string', - enum: ['auto', 'on', 'off', 'canvas'], + enum: ['auto', 'on', 'off'], markdownEnumDescriptions: [ localize('terminal.integrated.gpuAcceleration.auto', "Let VS Code detect which renderer will give the best experience."), localize('terminal.integrated.gpuAcceleration.on', "Enable GPU acceleration within the terminal."), localize('terminal.integrated.gpuAcceleration.off', "Disable GPU acceleration within the terminal. The terminal will render much slower when GPU acceleration is off but it should reliably work on all systems."), - localize('terminal.integrated.gpuAcceleration.canvas', "Use the terminal's fallback canvas renderer which uses a 2d context instead of webgl which may perform better on some systems. Note that some features are limited in the canvas renderer like opaque selection.") ], default: 'auto', description: localize('terminal.integrated.gpuAcceleration', "Controls whether the terminal will leverage the GPU to do its rendering.") diff --git a/yarn.lock b/yarn.lock index 2f4c572131c40..8b4c3ab95a869 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1913,11 +1913,6 @@ resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-2.0.5.tgz#325db42395cd49fe6c14057f9a900e427df8810e" integrity sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ== -"@xterm/addon-canvas@0.8.0-beta.17": - version "0.8.0-beta.17" - resolved "https://registry.yarnpkg.com/@xterm/addon-canvas/-/addon-canvas-0.8.0-beta.17.tgz#309630c738aa2e44742cdce5ee88fb8079fa652c" - integrity sha512-1km1RE02rxdbJWp1sev6Um6T/4tWlpEhJ88OP7xwfUFuedhFEby0JXmKzP7qB0cFzEvFTCq1bOAHSA3DX8vlFQ== - "@xterm/addon-image@0.9.0-beta.17": version "0.9.0-beta.17" resolved "https://registry.yarnpkg.com/@xterm/addon-image/-/addon-image-0.9.0-beta.17.tgz#343d0665a6060d4f893b4f2d32de6ccbbd00bb63" From a893b33b5f4384221b6368dd5f5fa04ddcbd07ed Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Fri, 26 Apr 2024 06:03:40 -0700 Subject: [PATCH 017/104] Add missing registers Fixes #211279 --- .../suggest/browser/terminalSuggestAddon.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon.ts b/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon.ts index c861284ce4729..6117f3ad916b2 100644 --- a/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon.ts +++ b/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon.ts @@ -382,16 +382,16 @@ export class SuggestAddon extends Disposable implements ITerminalAddon, ISuggest listInactiveFocusBackground: editorSuggestWidgetSelectedBackground, listInactiveFocusOutline: activeContrastBorder })); - this._suggestWidget.onDidSelect(async e => this.acceptSelectedSuggestion(e)); - this._suggestWidget.onDidHide(() => this._terminalSuggestWidgetVisibleContextKey.set(false)); - this._suggestWidget.onDidShow(() => { + this._register(this._suggestWidget.onDidSelect(async e => this.acceptSelectedSuggestion(e))); + this._register(this._suggestWidget.onDidHide(() => this._terminalSuggestWidgetVisibleContextKey.set(false))); + this._register(this._suggestWidget.onDidShow(() => { this._initialPromptInputState = { value: this._promptInputModel!.value, cursorIndex: this._promptInputModel!.cursorIndex, ghostTextIndex: this._promptInputModel!.ghostTextIndex }; this._terminalSuggestWidgetVisibleContextKey.set(true); - }); + })); } return this._suggestWidget; } From c398f717a947c0e0c406441b90cb341b4b16b8cc Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Fri, 26 Apr 2024 07:22:16 -0700 Subject: [PATCH 018/104] Consolidate ansi functions into strings.ts --- .../src/singlefolder-tests/terminal.test.ts | 4 +-- src/vs/base/common/ansi.ts | 35 ------------------- src/vs/base/common/strings.ts | 23 ++++++++++++ src/vs/base/test/common/ansi.test.ts | 33 ----------------- src/vs/base/test/common/strings.test.ts | 5 +++ .../common/xterm/shellIntegrationAddon.ts | 4 +-- .../contrib/remote/browser/urlFinder.ts | 4 +-- 7 files changed, 34 insertions(+), 74 deletions(-) delete mode 100644 src/vs/base/common/ansi.ts delete mode 100644 src/vs/base/test/common/ansi.test.ts 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 27e25dbf17fe0..7411d9c094a30 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/terminal.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/terminal.test.ts @@ -953,8 +953,8 @@ function sanitizeData(data: string): string { // Strip escape sequences so winpty/conpty doesn't cause flakiness, do for all platforms for // consistency - const terminalCodesRegex = /(?:\u001B|\u009B)[\[\]()#;?]*(?:(?:(?:[a-zA-Z0-9]*(?:;[a-zA-Z0-9]*)*)?\u0007)|(?:(?:\d{1,4}(?:;\d{0,4})*)?[0-9A-PR-TZcf-ntqry=><~]))/g; - data = data.replace(terminalCodesRegex, ''); + const CSI_SEQUENCE = /(:?(:?\x1b\[|\x9B)[=?>!]?[\d;:]*["$#'* ]?[a-zA-Z@^`{}|~])|(:?\x1b\].*?\x07)/g; + data = data.replace(CSI_SEQUENCE, ''); return data; } diff --git a/src/vs/base/common/ansi.ts b/src/vs/base/common/ansi.ts deleted file mode 100644 index 7a5d93bbfb827..0000000000000 --- a/src/vs/base/common/ansi.ts +++ /dev/null @@ -1,35 +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 { Lazy } from 'vs/base/common/lazy'; - -const ansiEscapeSequenceRegex = new Lazy(() => /(?:\u001B|\u009B)[\[\]()#;?]*(?:(?:(?:[a-zA-Z0-9]*(?:;[a-zA-Z0-9]*)*)?\u0007)|(?:(?:\d{1,4}(?:;\d{0,4})*)?[0-9A-PR-TZcf-ntqry=><~]))/g); -const promptNonPrintableCharactersRegex = new Lazy(() => /\\\[.*?\\\]/g); - -/** - * Strips ANSI escape sequences from a string. - * @param data The data to strip the ANSI escape sequences from. - * - * @example - * stripAnsiEscapeSequences('\u001b[31mHello, World!\u001b[0m'); - * // 'Hello, World!' - */ -export function stripAnsiEscapeSequences(data: string): string { - return data.replace(ansiEscapeSequenceRegex.value, ''); -} - -/** - * Strips ANSI escape sequences from a UNIX-style prompt string (eg. `$PS1`). - * @param data The data to strip the ANSI escape sequences from. - * - * @example - * stripAnsiEscapeSequencesFromPrompt('\n\\[\u001b[01;34m\\]\\w\\[\u001b[00m\\]\n\\[\u001b[1;32m\\]> \\[\u001b[0m\\]'); - * // '\n\\w\n> ' - */ -export function stripAnsiEscapeSequencesFromPrompt(data: string): string { - return (data - .replace(ansiEscapeSequenceRegex.value, '') - .replace(promptNonPrintableCharactersRegex.value, '')); -} diff --git a/src/vs/base/common/strings.ts b/src/vs/base/common/strings.ts index be372198ee714..51f74227383e1 100644 --- a/src/vs/base/common/strings.ts +++ b/src/vs/base/common/strings.ts @@ -786,6 +786,14 @@ export function* forAnsiStringParts(str: string) { } } +/** + * Strips ANSI escape sequences from a string. + * @param str The dastringa stringo strip the ANSI escape sequences from. + * + * @example + * removeAnsiEscapeCodes('\u001b[31mHello, World!\u001b[0m'); + * // 'Hello, World!' + */ export function removeAnsiEscapeCodes(str: string): string { if (str) { str = str.replace(CSI_SEQUENCE, ''); @@ -794,6 +802,21 @@ export function removeAnsiEscapeCodes(str: string): string { return str; } +const PROMPT_NON_PRINTABLE = /\\\[.*?\\\]/g; + +/** + * Strips ANSI escape sequences from a UNIX-style prompt string (eg. `$PS1`). + * @param str The string to strip the ANSI escape sequences from. + * + * @example + * removeAnsiEscapeCodesFromPrompt('\n\\[\u001b[01;34m\\]\\w\\[\u001b[00m\\]\n\\[\u001b[1;32m\\]> \\[\u001b[0m\\]'); + * // '\n\\w\n> ' + */ +export function removeAnsiEscapeCodesFromPrompt(str: string): string { + return removeAnsiEscapeCodes(str).replace(PROMPT_NON_PRINTABLE, ''); +} + + // -- UTF-8 BOM export const UTF8_BOM_CHARACTER = String.fromCharCode(CharCode.UTF8_BOM); diff --git a/src/vs/base/test/common/ansi.test.ts b/src/vs/base/test/common/ansi.test.ts deleted file mode 100644 index 0bdf32840cf21..0000000000000 --- a/src/vs/base/test/common/ansi.test.ts +++ /dev/null @@ -1,33 +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 { strictEqual } from 'assert'; -import { stripAnsiEscapeSequences, stripAnsiEscapeSequencesFromPrompt } from 'vs/base/common/ansi'; -import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils'; - -suite('ansi', () => { - ensureNoDisposablesAreLeakedInTestSuite(); - - suite('stripAnsiEscapeSequences', () => { - test('should strip simple SGR escape sequences', () => { - strictEqual(stripAnsiEscapeSequences('\u001b[31mHello, World!\u001b[0m'), 'Hello, World!'); - }); - test('should strip complex SGR escape sequences', () => { - strictEqual(stripAnsiEscapeSequences('\u001b[38;2;255;82;197;48;2;155;106;0mHello, World!\u001b[0m'), 'Hello, World!'); - }); - test('should strip ED, EL escape sequences', () => { - strictEqual(stripAnsiEscapeSequences('\u001b[KHello, World!\r\n\u001b[2J'), 'Hello, World!\r\n'); - }); - }); - - suite('stripAnsiEscapeSequencesFromPrompt', () => { - test('should strip simple SGR escape sequences', () => { - strictEqual(stripAnsiEscapeSequences('\u001b[31m$ \u001b[0m'), '$ '); - }); - test('should strip \[ and \] chars and their contents', () => { - strictEqual(stripAnsiEscapeSequencesFromPrompt('\n\\[\u001b[01;34m\\]\\w\\[\u001b[00m\\]\n\\[\u001b[1;32m\\]> \\[\u001b[0m\\]'), '\n\\w\n> '); - }); - }); -}); diff --git a/src/vs/base/test/common/strings.test.ts b/src/vs/base/test/common/strings.test.ts index 73c04ad723944..655bc2b42555d 100644 --- a/src/vs/base/test/common/strings.test.ts +++ b/src/vs/base/test/common/strings.test.ts @@ -538,6 +538,11 @@ suite('Strings', () => { } }); + test('removeAnsiEscapeCodesFromPrompt', () => { + assert.strictEqual(strings.removeAnsiEscapeCodesFromPrompt('\u001b[31m$ \u001b[0m'), '$ '); + assert.strictEqual(strings.removeAnsiEscapeCodesFromPrompt('\n\\[\u001b[01;34m\\]\\w\\[\u001b[00m\\]\n\\[\u001b[1;32m\\]> \\[\u001b[0m\\]'), '\n\\w\n> '); + }); + ensureNoDisposablesAreLeakedInTestSuite(); }); diff --git a/src/vs/platform/terminal/common/xterm/shellIntegrationAddon.ts b/src/vs/platform/terminal/common/xterm/shellIntegrationAddon.ts index 3404e18e5284a..de493bd36ab7f 100644 --- a/src/vs/platform/terminal/common/xterm/shellIntegrationAddon.ts +++ b/src/vs/platform/terminal/common/xterm/shellIntegrationAddon.ts @@ -21,7 +21,7 @@ import { BufferMarkCapability } from 'vs/platform/terminal/common/capabilities/b import type { ITerminalAddon, Terminal } from '@xterm/headless'; import { URI } from 'vs/base/common/uri'; import { sanitizeCwd } from 'vs/platform/terminal/common/terminalEnvironment'; -import { stripAnsiEscapeSequencesFromPrompt } from 'vs/base/common/ansi'; +import { removeAnsiEscapeCodesFromPrompt } from 'vs/base/common/strings'; /** @@ -383,7 +383,7 @@ export class ShellIntegrationAddon extends Disposable implements IShellIntegrati } switch (key) { case 'ContinuationPrompt': { - this._updateContinuationPrompt(stripAnsiEscapeSequencesFromPrompt(value)); + this._updateContinuationPrompt(removeAnsiEscapeCodesFromPrompt(value)); return true; } case 'Cwd': { diff --git a/src/vs/workbench/contrib/remote/browser/urlFinder.ts b/src/vs/workbench/contrib/remote/browser/urlFinder.ts index db63ef81eff01..e2995bb5f2d5b 100644 --- a/src/vs/workbench/contrib/remote/browser/urlFinder.ts +++ b/src/vs/workbench/contrib/remote/browser/urlFinder.ts @@ -7,7 +7,7 @@ import { ITerminalInstance, ITerminalService } from 'vs/workbench/contrib/termin import { Emitter } from 'vs/base/common/event'; import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; import { IDebugService, IDebugSession, IReplElement } from 'vs/workbench/contrib/debug/common/debug'; -import { stripAnsiEscapeSequences } from 'vs/base/common/ansi'; +import { removeAnsiEscapeCodes } from 'vs/base/common/strings'; export class UrlFinder extends Disposable { /** @@ -99,7 +99,7 @@ export class UrlFinder extends Disposable { private processData(data: string) { // strip ANSI terminal codes - data = stripAnsiEscapeSequences(data); + data = removeAnsiEscapeCodes(data); const urlMatches = data.match(UrlFinder.localUrlRegex) || []; if (urlMatches && urlMatches.length > 0) { urlMatches.forEach((match) => { From 94df2d801001e7a6aaff8254437d95f69da6273b Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 26 Apr 2024 16:46:05 +0200 Subject: [PATCH 019/104] Dataloss when renaming file two times (fix #211374) (#211457) * Dataloss when renaming file two times (fix #211374) * . --- .../textfile/common/textFileEditorModelManager.ts | 9 +++++++-- .../workingCopy/common/storedFileWorkingCopyManager.ts | 7 ++++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/services/textfile/common/textFileEditorModelManager.ts b/src/vs/workbench/services/textfile/common/textFileEditorModelManager.ts index 7aa0c00f8c1cc..ec6d4c95742f6 100644 --- a/src/vs/workbench/services/textfile/common/textFileEditorModelManager.ts +++ b/src/vs/workbench/services/textfile/common/textFileEditorModelManager.ts @@ -269,12 +269,17 @@ export class TextFileEditorModelManager extends Disposable implements ITextFileE await Promises.settled(modelsToRestore.map(async modelToRestore => { + // From this moment on, only operate on the canonical resource + // to fix a potential data loss issue: + // /~https://github.com/microsoft/vscode/issues/211374 + const target = this.uriIdentityService.asCanonicalUri(modelToRestore.target); + // restore the model at the target. if we have previous dirty content, we pass it // over to be used, otherwise we force a reload from disk. this is important // because we know the file has changed on disk after the move and the model might // have still existed with the previous state. this ensures that the model is not // tracking a stale state. - const restoredModel = await this.resolve(modelToRestore.target, { + const restoredModel = await this.resolve(target, { reload: { async: false }, // enforce a reload contents: modelToRestore.snapshot ? createTextBufferFactoryFromSnapshot(modelToRestore.snapshot) : undefined, encoding: modelToRestore.encoding @@ -287,7 +292,7 @@ export class TextFileEditorModelManager extends Disposable implements ITextFileE modelToRestore.languageId && modelToRestore.languageId !== PLAINTEXT_LANGUAGE_ID && restoredModel.getLanguageId() === PLAINTEXT_LANGUAGE_ID && - extname(modelToRestore.target) !== PLAINTEXT_EXTENSION + extname(target) !== PLAINTEXT_EXTENSION ) { restoredModel.updateTextEditorModel(undefined, modelToRestore.languageId); } diff --git a/src/vs/workbench/services/workingCopy/common/storedFileWorkingCopyManager.ts b/src/vs/workbench/services/workingCopy/common/storedFileWorkingCopyManager.ts index 547244e4e6da7..f445e7d36ddef 100644 --- a/src/vs/workbench/services/workingCopy/common/storedFileWorkingCopyManager.ts +++ b/src/vs/workbench/services/workingCopy/common/storedFileWorkingCopyManager.ts @@ -411,12 +411,17 @@ export class StoredFileWorkingCopyManager await Promises.settled(workingCopiesToRestore.map(async workingCopyToRestore => { + // From this moment on, only operate on the canonical resource + // to fix a potential data loss issue: + // /~https://github.com/microsoft/vscode/issues/211374 + const target = this.uriIdentityService.asCanonicalUri(workingCopyToRestore.target); + // Restore the working copy at the target. if we have previous dirty content, we pass it // over to be used, otherwise we force a reload from disk. this is important // because we know the file has changed on disk after the move and the working copy might // have still existed with the previous state. this ensures that the working copy is not // tracking a stale state. - await this.resolve(workingCopyToRestore.target, { + await this.resolve(target, { reload: { async: false }, // enforce a reload contents: workingCopyToRestore.snapshot }); From 68a3986487a9675b457374e4c76869da566c5f36 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Fri, 26 Apr 2024 09:06:37 -0700 Subject: [PATCH 020/104] Change method of fetching pwsh completions --- .../browser/media/shellIntegration.ps1 | 74 ++++++++++++--- .../suggest/browser/terminalSuggestAddon.ts | 90 +++++++++++++++---- 2 files changed, 135 insertions(+), 29 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/browser/media/shellIntegration.ps1 b/src/vs/workbench/contrib/terminal/browser/media/shellIntegration.ps1 index c22f7d642247b..41d146b660687 100644 --- a/src/vs/workbench/contrib/terminal/browser/media/shellIntegration.ps1 +++ b/src/vs/workbench/contrib/terminal/browser/media/shellIntegration.ps1 @@ -174,12 +174,12 @@ function Set-MappedKeyHandlers { } # Suggest trigger characters - Set-PSReadLineKeyHandler -Chord "-" -ScriptBlock { - [Microsoft.PowerShell.PSConsoleReadLine]::Insert("-") - if (!$Global:__VSCodeHaltCompletions) { - Send-Completions - } - } + # Set-PSReadLineKeyHandler -Chord "-" -ScriptBlock { + # [Microsoft.PowerShell.PSConsoleReadLine]::Insert("-") + # if (!$Global:__VSCodeHaltCompletions) { + # Send-Completions + # } + # } Set-PSReadLineKeyHandler -Chord 'F12,y' -ScriptBlock { $Global:__VSCodeHaltCompletions = $true @@ -188,6 +188,13 @@ function Set-MappedKeyHandlers { Set-PSReadLineKeyHandler -Chord 'F12,z' -ScriptBlock { $Global:__VSCodeHaltCompletions = $false } + + # TODO: When does this invalidate? Installing a new module could add new commands + # Commands are expensive to complete and send over, do this ones for the empty string so we + # don't need to do it each time the user requests. + $result = "$([char]0x1b)]633;CompletionsPwshCommands;commands;" + $result += [System.Management.Automation.CompletionCompleters]::CompleteCommand('') | ConvertTo-Json -Compress + Write-Host -NoNewLine $result } } @@ -200,16 +207,59 @@ function Send-Completions { [Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$commandLine, [ref]$cursorIndex) $completionPrefix = $commandLine - # Get completions + # Start completions sequence $result = "$([char]0x1b)]633;Completions" + + # Get completions if ($completionPrefix.Length -gt 0) { - # Get and send completions - $completions = TabExpansion2 -inputScript $completionPrefix -cursorColumn $cursorIndex - if ($null -ne $completions.CompletionMatches) { - $result += ";$($completions.ReplacementIndex);$($completions.ReplacementLength);$($cursorIndex);" - $result += $completions.CompletionMatches | ConvertTo-Json -Compress + # If there is a space in the input, defer to TabExpansion2 as it's more complicated to + # determine valid completions + if ($completionPrefix.Contains(' ')) { + $completions = TabExpansion2 -inputScript $completionPrefix -cursorColumn $cursorIndex + if ($null -ne $completions.CompletionMatches) { + $result += ";$($completions.ReplacementIndex);$($completions.ReplacementLength);$($cursorIndex);" + $result += $completions.CompletionMatches | ConvertTo-Json -Compress + } + } + # If there is no space, get completions using CompletionCompleters as it gives us more + # control and works on the empty string + else { + # $completions = TabExpansion2 -inputScript $completionPrefix -cursorColumn $cursorIndex + # if ($null -ne $completions.CompletionMatches) { + # $result += ";$($completions.ReplacementIndex);$($completions.ReplacementLength);$($cursorIndex);" + # $result += $completions.CompletionMatches | ConvertTo-Json -Compress + # } + # Get and send completions, note that CompleteCommand isn't included here as it's expensive + $completions = $( + ([System.Management.Automation.CompletionCompleters]::CompleteFilename($completionPrefix)); + ([System.Management.Automation.CompletionCompleters]::CompleteVariable($completionPrefix)); + ) + if ($null -ne $completions) { + $result += ";$($completions.ReplacementIndex);$($completions.ReplacementLength);$($cursorIndex);" + $result += $completions | ConvertTo-Json -Compress + } else { + $result += ";0;$($completionPrefix.Length);$($completionPrefix.Length);[]" + } + } + } else { + # TODO: Consolidate this case with the above + # TODO: Try use this approach after the last whitespace for everything so intellisense is always consistent + + # Special case when the prefix is empty since TabExpansion2 doesn't handle it + if ($completionPrefix.Length -eq 0) { + # Get and send completions + $completions = $( + ([System.Management.Automation.CompletionCompleters]::CompleteFilename('')); + ([System.Management.Automation.CompletionCompleters]::CompleteVariable('')); + ) + if ($null -ne $completions) { + $result += ";0;0;0;" + $result += $completions | ConvertTo-Json -Compress + } } } + + # End completions sequence $result += "`a" Write-Host -NoNewLine $result diff --git a/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon.ts b/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon.ts index 6117f3ad916b2..f46bee2e07398 100644 --- a/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon.ts +++ b/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon.ts @@ -26,6 +26,7 @@ import { ShellIntegrationOscPs } from 'vs/platform/terminal/common/xterm/shellIn const enum VSCodeOscPt { Completions = 'Completions', + CompletionsPwshCommands = 'CompletionsPwshCommands', CompletionsBash = 'CompletionsBash', CompletionsBashFirstWord = 'CompletionsBashFirstWord' } @@ -135,13 +136,24 @@ export class SuggestAddon extends Disposable implements ITerminalAddon, ISuggest } private _sync(promptInputState: IPromptInputModelState): void { + + if ( + (!this._mostRecentPromptInputState || promptInputState.cursorIndex > this._mostRecentPromptInputState.cursorIndex) && + (promptInputState.cursorIndex === 1 || promptInputState.value.substring(0, promptInputState.cursorIndex).match(/\s[^\s]$/)) + ) { + // TODO: Debounce? Prevent this flooding the channel + this._onAcceptedCompletion.fire('\x1b[24~e'); + } + this._mostRecentPromptInputState = promptInputState; + // this._onAcceptedCompletion.fire('\x1b[24~e'); if (!this._promptInputModel || !this._terminal || !this._suggestWidget || !this._initialPromptInputState) { return; } this._currentPromptInputState = promptInputState; + // Hide the widget if the cursor moves to the left of the initial position as the // completions are no longer valid if (this._currentPromptInputState.cursorIndex < this._initialPromptInputState.cursorIndex) { @@ -153,6 +165,10 @@ export class SuggestAddon extends Disposable implements ITerminalAddon, ISuggest const inputBeforeCursor = this._currentPromptInputState.value.substring(0, this._currentPromptInputState.cursorIndex); this._cursorIndexDelta = this._currentPromptInputState.cursorIndex - this._initialPromptInputState.cursorIndex; + console.log('setLineContext', { + inputBeforeCursor, + cursorIndexDelta: this._cursorIndexDelta + }); this._suggestWidget.setLineContext(new LineContext(inputBeforeCursor, this._cursorIndexDelta)); } @@ -191,6 +207,8 @@ export class SuggestAddon extends Disposable implements ITerminalAddon, ISuggest case VSCodeOscPt.Completions: this._handleCompletionsSequence(this._terminal, data, command, args); return true; + case VSCodeOscPt.CompletionsPwshCommands: + this._handleCompletionsPwshCommandsSequence(this._terminal, data, command, args); case VSCodeOscPt.CompletionsBash: this._handleCompletionsBashSequence(this._terminal, data, command, args); return true; @@ -204,18 +222,25 @@ export class SuggestAddon extends Disposable implements ITerminalAddon, ISuggest private _handleCompletionsSequence(terminal: Terminal, data: string, command: string, args: string[]): void { // Nothing to handle if the terminal is not attached - if (!terminal.element || !this._enableWidget) { + if (!terminal.element || !this._enableWidget || !this._promptInputModel) { return; } - const replacementIndex = parseInt(args[0]); - const replacementLength = parseInt(args[1]); - if (!args[3]) { - this._onBell.fire(); - return; - } + let replacementIndex = 0; //args.length === 0 ? 0 : parseInt(args[0]); + let replacementLength = this._promptInputModel.cursorIndex; //args.length === 0 ? 0 : parseInt(args[1]); - let completionList: IPwshCompletion[] | IPwshCompletion = JSON.parse(data.slice(command.length + args[0].length + args[1].length + args[2].length + 4/*semi-colons*/)); + console.log({ + replacementIndex, + replacementLength + }); + // TODO: Add bell back? + // if (!args[3]) { + // this._onBell.fire(); + // return; + // } + + const payload = data.slice(command.length + args[0].length + args[1].length + args[2].length + 4/*semi-colons*/); + let completionList: IPwshCompletion[] | IPwshCompletion = args.length === 0 || payload.length === 0 ? [] : JSON.parse(payload); if (!Array.isArray(completionList)) { completionList = [completionList]; } @@ -227,7 +252,23 @@ export class SuggestAddon extends Disposable implements ITerminalAddon, ISuggest }); }); - this._leadingLineContent = completions[0].completion.label.slice(0, replacementLength); + this._leadingLineContent = this._promptInputModel.value.substring(0, this._promptInputModel.cursorIndex); + + // If there's no space it means this is a command, add cached commands list to completions + if (!this._leadingLineContent.trim().includes(' ')) { + completions.push(...this._cachedPwshCommands); + } else { + replacementIndex = parseInt(args[0]); + replacementLength = parseInt(args[1]); + this._leadingLineContent = completions[0].completion.label.slice(0, replacementLength); + } + + console.log({ + replacementIndex, + replacementLength, + leadingLineContent: this._leadingLineContent + }); + this._cursorIndexDelta = 0; const model = new SimpleCompletionModel(completions, new LineContext(this._leadingLineContent, replacementIndex), replacementIndex, replacementLength); if (completions.length === 1) { @@ -240,6 +281,28 @@ export class SuggestAddon extends Disposable implements ITerminalAddon, ISuggest this._handleCompletionModel(model); } + private _cachedPwshCommands: Set = new Set(); + private _handleCompletionsPwshCommandsSequence(terminal: Terminal, data: string, command: string, args: string[]): void { + const type = args[0]; + let completionList: IPwshCompletion[] | IPwshCompletion = JSON.parse(data.slice(command.length + type.length + 2/*semi-colons*/)); + if (!Array.isArray(completionList)) { + completionList = [completionList]; + } + const set = this._cachedPwshCommands; + set.clear(); + + const completions = completionList.map((e: any) => { + return new SimpleCompletionItem({ + label: e.CompletionText, + icon: pwshTypeToIconMap[e.ResultType], + detail: e.ToolTip + }); + }); + for (const c of completions) { + set.add(c); + } + } + // TODO: These aren't persisted across reloads // TODO: Allow triggering anywhere in the first word based on the cached completions private _cachedBashAliases: Set = new Set(); @@ -384,14 +447,7 @@ export class SuggestAddon extends Disposable implements ITerminalAddon, ISuggest })); this._register(this._suggestWidget.onDidSelect(async e => this.acceptSelectedSuggestion(e))); this._register(this._suggestWidget.onDidHide(() => this._terminalSuggestWidgetVisibleContextKey.set(false))); - this._register(this._suggestWidget.onDidShow(() => { - this._initialPromptInputState = { - value: this._promptInputModel!.value, - cursorIndex: this._promptInputModel!.cursorIndex, - ghostTextIndex: this._promptInputModel!.ghostTextIndex - }; - this._terminalSuggestWidgetVisibleContextKey.set(true); - })); + this._register(this._suggestWidget.onDidShow(() => this._terminalSuggestWidgetVisibleContextKey.set(true))); } return this._suggestWidget; } From 506d3d214e4192b6dfbc9e09543768cc596a3b55 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Fri, 26 Apr 2024 09:09:09 -0700 Subject: [PATCH 021/104] Fix error --- .../terminalContrib/suggest/browser/terminalSuggestAddon.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon.ts b/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon.ts index f46bee2e07398..faa5fcb396f79 100644 --- a/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon.ts +++ b/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon.ts @@ -260,7 +260,7 @@ export class SuggestAddon extends Disposable implements ITerminalAddon, ISuggest } else { replacementIndex = parseInt(args[0]); replacementLength = parseInt(args[1]); - this._leadingLineContent = completions[0].completion.label.slice(0, replacementLength); + this._leadingLineContent = completions[0]?.completion.label.slice(0, replacementLength) ?? ''; } console.log({ From e749f4e5f7bce358b7bcbe32b71c181e850dde65 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Fri, 26 Apr 2024 09:16:45 -0700 Subject: [PATCH 022/104] Clean up --- .../browser/media/shellIntegration.ps1 | 89 +++++++++---------- .../suggest/browser/terminalSuggestAddon.ts | 25 +----- 2 files changed, 45 insertions(+), 69 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/browser/media/shellIntegration.ps1 b/src/vs/workbench/contrib/terminal/browser/media/shellIntegration.ps1 index 41d146b660687..af837986a78f3 100644 --- a/src/vs/workbench/contrib/terminal/browser/media/shellIntegration.ps1 +++ b/src/vs/workbench/contrib/terminal/browser/media/shellIntegration.ps1 @@ -210,54 +210,53 @@ function Send-Completions { # Start completions sequence $result = "$([char]0x1b)]633;Completions" - # Get completions - if ($completionPrefix.Length -gt 0) { - # If there is a space in the input, defer to TabExpansion2 as it's more complicated to - # determine valid completions - if ($completionPrefix.Contains(' ')) { - $completions = TabExpansion2 -inputScript $completionPrefix -cursorColumn $cursorIndex - if ($null -ne $completions.CompletionMatches) { - $result += ";$($completions.ReplacementIndex);$($completions.ReplacementLength);$($cursorIndex);" - $result += $completions.CompletionMatches | ConvertTo-Json -Compress - } + # If there is a space in the input, defer to TabExpansion2 as it's more complicated to + # determine what type of completions to use + if ($completionPrefix.Contains(' ')) { + $completions = TabExpansion2 -inputScript $completionPrefix -cursorColumn $cursorIndex + if ($null -ne $completions.CompletionMatches) { + $result += ";$($completions.ReplacementIndex);$($completions.ReplacementLength);$($cursorIndex);" + $result += $completions.CompletionMatches | ConvertTo-Json -Compress } - # If there is no space, get completions using CompletionCompleters as it gives us more - # control and works on the empty string - else { - # $completions = TabExpansion2 -inputScript $completionPrefix -cursorColumn $cursorIndex - # if ($null -ne $completions.CompletionMatches) { - # $result += ";$($completions.ReplacementIndex);$($completions.ReplacementLength);$($cursorIndex);" - # $result += $completions.CompletionMatches | ConvertTo-Json -Compress - # } - # Get and send completions, note that CompleteCommand isn't included here as it's expensive - $completions = $( - ([System.Management.Automation.CompletionCompleters]::CompleteFilename($completionPrefix)); - ([System.Management.Automation.CompletionCompleters]::CompleteVariable($completionPrefix)); - ) - if ($null -ne $completions) { - $result += ";$($completions.ReplacementIndex);$($completions.ReplacementLength);$($cursorIndex);" - $result += $completions | ConvertTo-Json -Compress - } else { - $result += ";0;$($completionPrefix.Length);$($completionPrefix.Length);[]" - } - } - } else { - # TODO: Consolidate this case with the above - # TODO: Try use this approach after the last whitespace for everything so intellisense is always consistent - - # Special case when the prefix is empty since TabExpansion2 doesn't handle it - if ($completionPrefix.Length -eq 0) { - # Get and send completions - $completions = $( - ([System.Management.Automation.CompletionCompleters]::CompleteFilename('')); - ([System.Management.Automation.CompletionCompleters]::CompleteVariable('')); - ) - if ($null -ne $completions) { - $result += ";0;0;0;" - $result += $completions | ConvertTo-Json -Compress - } + } + # If there is no space, get completions using CompletionCompleters as it gives us more + # control and works on the empty string + else { + # $completions = TabExpansion2 -inputScript $completionPrefix -cursorColumn $cursorIndex + # if ($null -ne $completions.CompletionMatches) { + # $result += ";$($completions.ReplacementIndex);$($completions.ReplacementLength);$($cursorIndex);" + # $result += $completions.CompletionMatches | ConvertTo-Json -Compress + # } + # Get and send completions, note that CompleteCommand isn't included here as it's expensive + $completions = $( + ([System.Management.Automation.CompletionCompleters]::CompleteFilename($completionPrefix)); + ([System.Management.Automation.CompletionCompleters]::CompleteVariable($completionPrefix)); + ) + this + if ($null -ne $completions) { + $result += ";$($completions.ReplacementIndex);$($completions.ReplacementLength);$($cursorIndex);" + $result += $completions | ConvertTo-Json -Compress + } else { + $result += ";0;$($completionPrefix.Length);$($completionPrefix.Length);[]" } } + # } else { + # # TODO: Consolidate this case with the above + # # TODO: Try use this approach after the last whitespace for everything so intellisense is always consistent + + # # Special case when the prefix is empty since TabExpansion2 doesn't handle it + # if ($completionPrefix.Length -eq 0) { + # # Get and send completions + # $completions = $( + # ([System.Management.Automation.CompletionCompleters]::CompleteFilename('')); + # ([System.Management.Automation.CompletionCompleters]::CompleteVariable('')); + # ) + # if ($null -ne $completions) { + # $result += ";0;0;0;" + # $result += $completions | ConvertTo-Json -Compress + # } + # } + # } # End completions sequence $result += "`a" diff --git a/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon.ts b/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon.ts index faa5fcb396f79..68e9c6388c955 100644 --- a/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon.ts +++ b/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon.ts @@ -136,11 +136,11 @@ export class SuggestAddon extends Disposable implements ITerminalAddon, ISuggest } private _sync(promptInputState: IPromptInputModelState): void { - if ( (!this._mostRecentPromptInputState || promptInputState.cursorIndex > this._mostRecentPromptInputState.cursorIndex) && (promptInputState.cursorIndex === 1 || promptInputState.value.substring(0, promptInputState.cursorIndex).match(/\s[^\s]$/)) ) { + // TODO: Allow the user to configure when completions are triggered - this is equivalent to editor.quickSuggestions // TODO: Debounce? Prevent this flooding the channel this._onAcceptedCompletion.fire('\x1b[24~e'); } @@ -229,16 +229,6 @@ export class SuggestAddon extends Disposable implements ITerminalAddon, ISuggest let replacementIndex = 0; //args.length === 0 ? 0 : parseInt(args[0]); let replacementLength = this._promptInputModel.cursorIndex; //args.length === 0 ? 0 : parseInt(args[1]); - console.log({ - replacementIndex, - replacementLength - }); - // TODO: Add bell back? - // if (!args[3]) { - // this._onBell.fire(); - // return; - // } - const payload = data.slice(command.length + args[0].length + args[1].length + args[2].length + 4/*semi-colons*/); let completionList: IPwshCompletion[] | IPwshCompletion = args.length === 0 || payload.length === 0 ? [] : JSON.parse(payload); if (!Array.isArray(completionList)) { @@ -263,21 +253,8 @@ export class SuggestAddon extends Disposable implements ITerminalAddon, ISuggest this._leadingLineContent = completions[0]?.completion.label.slice(0, replacementLength) ?? ''; } - console.log({ - replacementIndex, - replacementLength, - leadingLineContent: this._leadingLineContent - }); - this._cursorIndexDelta = 0; const model = new SimpleCompletionModel(completions, new LineContext(this._leadingLineContent, replacementIndex), replacementIndex, replacementLength); - if (completions.length === 1) { - const insertText = completions[0].completion.label.substring(replacementLength); - if (insertText.length === 0) { - this._onBell.fire(); - return; - } - } this._handleCompletionModel(model); } From 77927bcdec61626961127fa50d711589bc17e2ff Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Fri, 26 Apr 2024 09:25:37 -0700 Subject: [PATCH 023/104] Quick suggestions vs trigger chars --- .../browser/media/shellIntegration.ps1 | 13 ++++++++++- .../suggest/browser/terminalSuggestAddon.ts | 23 +++++++++++++------ 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/browser/media/shellIntegration.ps1 b/src/vs/workbench/contrib/terminal/browser/media/shellIntegration.ps1 index af837986a78f3..303859ab04bb7 100644 --- a/src/vs/workbench/contrib/terminal/browser/media/shellIntegration.ps1 +++ b/src/vs/workbench/contrib/terminal/browser/media/shellIntegration.ps1 @@ -180,6 +180,18 @@ function Set-MappedKeyHandlers { # Send-Completions # } # } + # Set-PSReadLineKeyHandler -Chord "\" -ScriptBlock { + # [Microsoft.PowerShell.PSConsoleReadLine]::Insert("\") + # if (!$Global:__VSCodeHaltCompletions) { + # Send-Completions + # } + # } + # Set-PSReadLineKeyHandler -Chord "/" -ScriptBlock { + # [Microsoft.PowerShell.PSConsoleReadLine]::Insert("/") + # if (!$Global:__VSCodeHaltCompletions) { + # Send-Completions + # } + # } Set-PSReadLineKeyHandler -Chord 'F12,y' -ScriptBlock { $Global:__VSCodeHaltCompletions = $true @@ -232,7 +244,6 @@ function Send-Completions { ([System.Management.Automation.CompletionCompleters]::CompleteFilename($completionPrefix)); ([System.Management.Automation.CompletionCompleters]::CompleteVariable($completionPrefix)); ) - this if ($null -ne $completions) { $result += ";$($completions.ReplacementIndex);$($completions.ReplacementLength);$($cursorIndex);" $result += $completions | ConvertTo-Json -Compress diff --git a/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon.ts b/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon.ts index 68e9c6388c955..91a6a932dd7a9 100644 --- a/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon.ts +++ b/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon.ts @@ -136,13 +136,22 @@ export class SuggestAddon extends Disposable implements ITerminalAddon, ISuggest } private _sync(promptInputState: IPromptInputModelState): void { - if ( - (!this._mostRecentPromptInputState || promptInputState.cursorIndex > this._mostRecentPromptInputState.cursorIndex) && - (promptInputState.cursorIndex === 1 || promptInputState.value.substring(0, promptInputState.cursorIndex).match(/\s[^\s]$/)) - ) { - // TODO: Allow the user to configure when completions are triggered - this is equivalent to editor.quickSuggestions - // TODO: Debounce? Prevent this flooding the channel - this._onAcceptedCompletion.fire('\x1b[24~e'); + if (!this._terminalSuggestWidgetVisibleContextKey.get()) { + // If input has been added + if (!this._mostRecentPromptInputState || promptInputState.cursorIndex > this._mostRecentPromptInputState.cursorIndex) { + // Quick suggestions + if (promptInputState.cursorIndex === 1 || promptInputState.value.substring(0, promptInputState.cursorIndex).match(/\s[^\s]$/)) { + // TODO: Allow the user to configure when completions are triggered - this is equivalent to editor.quickSuggestions + // TODO: Debounce? Prevent this flooding the channel + this._onAcceptedCompletion.fire('\x1b[24~e'); + } + + // Trigger characters + const lastChar = promptInputState.value.at(promptInputState.cursorIndex - 1); + if (lastChar?.match(/[\\\/\-]/)) { + this._onAcceptedCompletion.fire('\x1b[24~e'); + } + } } this._mostRecentPromptInputState = promptInputState; From 5cb29dbb273adebb8585317a0545ffda27e16ef0 Mon Sep 17 00:00:00 2001 From: Megan Rogge Date: Fri, 26 Apr 2024 09:51:42 -0700 Subject: [PATCH 024/104] fix task error telemetry reported bug (#211471) fix #211000 --- src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts b/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts index 5e0eed955c802..c4d6e65f891b1 100644 --- a/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts +++ b/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts @@ -460,7 +460,7 @@ export class TerminalTaskSystem extends Disposable implements ITaskSystem { public terminateAll(): Promise { const promises: Promise[] = []; for (const [key, terminalData] of Object.entries(this._activeTasks)) { - const terminal = terminalData.terminal; + const terminal = terminalData?.terminal; if (terminal) { promises.push(new Promise((resolve, reject) => { const onExit = terminal.onExit(() => { From a7755eed01d9930aaac7ba8517c9a9ca4872a5b1 Mon Sep 17 00:00:00 2001 From: Megan Rogge Date: Fri, 26 Apr 2024 10:08:04 -0700 Subject: [PATCH 025/104] rm audio cue, alert config, mentions of audio cue (#211475) rm audio cue, alert config --- .../browser/accessibilitySignalService.ts | 61 ++----- .../browser/accessibility.contribution.ts | 2 - .../browser/accessibilityConfiguration.ts | 116 +------------ .../browser/audioCueConfiguration.ts | 163 ------------------ 4 files changed, 27 insertions(+), 315 deletions(-) delete mode 100644 src/vs/workbench/contrib/accessibility/browser/audioCueConfiguration.ts diff --git a/src/vs/platform/accessibilitySignal/browser/accessibilitySignalService.ts b/src/vs/platform/accessibilitySignal/browser/accessibilitySignalService.ts index 166c08ff25635..ba277dbc24e87 100644 --- a/src/vs/platform/accessibilitySignal/browser/accessibilitySignalService.ts +++ b/src/vs/platform/accessibilitySignal/browser/accessibilitySignalService.ts @@ -318,29 +318,6 @@ export class SoundSource { } } -export const enum AccessibilityAlertSettingId { - Save = 'accessibility.alert.save', - Format = 'accessibility.alert.format', - Clear = 'accessibility.alert.clear', - Breakpoint = 'accessibility.alert.breakpoint', - Error = 'accessibility.alert.error', - Warning = 'accessibility.alert.warning', - FoldedArea = 'accessibility.alert.foldedArea', - TerminalQuickFix = 'accessibility.alert.terminalQuickFix', - TerminalBell = 'accessibility.alert.terminalBell', - TerminalCommandFailed = 'accessibility.alert.terminalCommandFailed', - TaskCompleted = 'accessibility.alert.taskCompleted', - TaskFailed = 'accessibility.alert.taskFailed', - ChatRequestSent = 'accessibility.alert.chatRequestSent', - NotebookCellCompleted = 'accessibility.alert.notebookCellCompleted', - NotebookCellFailed = 'accessibility.alert.notebookCellFailed', - OnDebugBreak = 'accessibility.alert.onDebugBreak', - NoInlayHints = 'accessibility.alert.noInlayHints', - LineHasBreakpoint = 'accessibility.alert.lineHasBreakpoint', - Progress = 'accessibility.alert.chatResponseProgress' -} - - export class AccessibilitySignal { private constructor( public readonly sound: SoundSource, @@ -363,7 +340,7 @@ export class AccessibilitySignal { }; legacySoundSettingsKey?: string; settingsKey: string; - legacyAnnouncementSettingsKey?: AccessibilityAlertSettingId; + legacyAnnouncementSettingsKey?: string; announcementMessage?: string; }): AccessibilitySignal { const soundSource = new SoundSource('randomOneOf' in options.sound ? options.sound.randomOneOf : [options.sound]); @@ -400,7 +377,7 @@ export class AccessibilitySignal { name: localize('accessibilitySignals.lineHasError.name', 'Error on Line'), sound: Sound.error, legacySoundSettingsKey: 'audioCues.lineHasError', - legacyAnnouncementSettingsKey: AccessibilityAlertSettingId.Error, + legacyAnnouncementSettingsKey: 'accessibility.alert.error', announcementMessage: localize('accessibility.signals.lineHasError', 'Error on Line'), settingsKey: 'accessibility.signals.lineHasError', }); @@ -409,7 +386,7 @@ export class AccessibilitySignal { name: localize('accessibilitySignals.lineHasWarning.name', 'Warning on Line'), sound: Sound.warning, legacySoundSettingsKey: 'audioCues.lineHasWarning', - legacyAnnouncementSettingsKey: AccessibilityAlertSettingId.Warning, + legacyAnnouncementSettingsKey: 'accessibility.alert.warning', announcementMessage: localize('accessibility.signals.lineHasWarning', 'Warning on Line'), settingsKey: 'accessibility.signals.lineHasWarning', }); @@ -417,7 +394,7 @@ export class AccessibilitySignal { name: localize('accessibilitySignals.lineHasFoldedArea.name', 'Folded Area on Line'), sound: Sound.foldedArea, legacySoundSettingsKey: 'audioCues.lineHasFoldedArea', - legacyAnnouncementSettingsKey: AccessibilityAlertSettingId.FoldedArea, + legacyAnnouncementSettingsKey: 'accessibility.alert.foldedArea', announcementMessage: localize('accessibility.signals.lineHasFoldedArea', 'Folded'), settingsKey: 'accessibility.signals.lineHasFoldedArea', }); @@ -425,7 +402,7 @@ export class AccessibilitySignal { name: localize('accessibilitySignals.lineHasBreakpoint.name', 'Breakpoint on Line'), sound: Sound.break, legacySoundSettingsKey: 'audioCues.lineHasBreakpoint', - legacyAnnouncementSettingsKey: AccessibilityAlertSettingId.Breakpoint, + legacyAnnouncementSettingsKey: 'accessibility.alert.breakpoint', announcementMessage: localize('accessibility.signals.lineHasBreakpoint', 'Breakpoint'), settingsKey: 'accessibility.signals.lineHasBreakpoint', }); @@ -440,7 +417,7 @@ export class AccessibilitySignal { name: localize('accessibilitySignals.terminalQuickFix.name', 'Terminal Quick Fix'), sound: Sound.quickFixes, legacySoundSettingsKey: 'audioCues.terminalQuickFix', - legacyAnnouncementSettingsKey: AccessibilityAlertSettingId.TerminalQuickFix, + legacyAnnouncementSettingsKey: 'accessibility.alert.terminalQuickFix', announcementMessage: localize('accessibility.signals.terminalQuickFix', 'Quick Fix'), settingsKey: 'accessibility.signals.terminalQuickFix', }); @@ -449,7 +426,7 @@ export class AccessibilitySignal { name: localize('accessibilitySignals.onDebugBreak.name', 'Debugger Stopped on Breakpoint'), sound: Sound.break, legacySoundSettingsKey: 'audioCues.onDebugBreak', - legacyAnnouncementSettingsKey: AccessibilityAlertSettingId.OnDebugBreak, + legacyAnnouncementSettingsKey: 'accessibility.alert.onDebugBreak', announcementMessage: localize('accessibility.signals.onDebugBreak', 'Breakpoint'), settingsKey: 'accessibility.signals.onDebugBreak', }); @@ -458,7 +435,7 @@ export class AccessibilitySignal { name: localize('accessibilitySignals.noInlayHints', 'No Inlay Hints on Line'), sound: Sound.error, legacySoundSettingsKey: 'audioCues.noInlayHints', - legacyAnnouncementSettingsKey: AccessibilityAlertSettingId.NoInlayHints, + legacyAnnouncementSettingsKey: 'accessibility.alert.noInlayHints', announcementMessage: localize('accessibility.signals.noInlayHints', 'No Inlay Hints'), settingsKey: 'accessibility.signals.noInlayHints', }); @@ -467,7 +444,7 @@ export class AccessibilitySignal { name: localize('accessibilitySignals.taskCompleted', 'Task Completed'), sound: Sound.taskCompleted, legacySoundSettingsKey: 'audioCues.taskCompleted', - legacyAnnouncementSettingsKey: AccessibilityAlertSettingId.TaskCompleted, + legacyAnnouncementSettingsKey: 'accessibility.alert.taskCompleted', announcementMessage: localize('accessibility.signals.taskCompleted', 'Task Completed'), settingsKey: 'accessibility.signals.taskCompleted', }); @@ -476,7 +453,7 @@ export class AccessibilitySignal { name: localize('accessibilitySignals.taskFailed', 'Task Failed'), sound: Sound.taskFailed, legacySoundSettingsKey: 'audioCues.taskFailed', - legacyAnnouncementSettingsKey: AccessibilityAlertSettingId.TaskFailed, + legacyAnnouncementSettingsKey: 'accessibility.alert.taskFailed', announcementMessage: localize('accessibility.signals.taskFailed', 'Task Failed'), settingsKey: 'accessibility.signals.taskFailed', }); @@ -485,7 +462,7 @@ export class AccessibilitySignal { name: localize('accessibilitySignals.terminalCommandFailed', 'Terminal Command Failed'), sound: Sound.error, legacySoundSettingsKey: 'audioCues.terminalCommandFailed', - legacyAnnouncementSettingsKey: AccessibilityAlertSettingId.TerminalCommandFailed, + legacyAnnouncementSettingsKey: 'accessibility.alert.terminalCommandFailed', announcementMessage: localize('accessibility.signals.terminalCommandFailed', 'Command Failed'), settingsKey: 'accessibility.signals.terminalCommandFailed', }); @@ -494,7 +471,7 @@ export class AccessibilitySignal { name: localize('accessibilitySignals.terminalBell', 'Terminal Bell'), sound: Sound.terminalBell, legacySoundSettingsKey: 'audioCues.terminalBell', - legacyAnnouncementSettingsKey: AccessibilityAlertSettingId.TerminalBell, + legacyAnnouncementSettingsKey: 'accessibility.alert.terminalBell', announcementMessage: localize('accessibility.signals.terminalBell', 'Terminal Bell'), settingsKey: 'accessibility.signals.terminalBell', }); @@ -503,7 +480,7 @@ export class AccessibilitySignal { name: localize('accessibilitySignals.notebookCellCompleted', 'Notebook Cell Completed'), sound: Sound.taskCompleted, legacySoundSettingsKey: 'audioCues.notebookCellCompleted', - legacyAnnouncementSettingsKey: AccessibilityAlertSettingId.NotebookCellCompleted, + legacyAnnouncementSettingsKey: 'accessibility.alert.notebookCellCompleted', announcementMessage: localize('accessibility.signals.notebookCellCompleted', 'Notebook Cell Completed'), settingsKey: 'accessibility.signals.notebookCellCompleted', }); @@ -512,7 +489,7 @@ export class AccessibilitySignal { name: localize('accessibilitySignals.notebookCellFailed', 'Notebook Cell Failed'), sound: Sound.taskFailed, legacySoundSettingsKey: 'audioCues.notebookCellFailed', - legacyAnnouncementSettingsKey: AccessibilityAlertSettingId.NotebookCellFailed, + legacyAnnouncementSettingsKey: 'accessibility.alert.notebookCellFailed', announcementMessage: localize('accessibility.signals.notebookCellFailed', 'Notebook Cell Failed'), settingsKey: 'accessibility.signals.notebookCellFailed', }); @@ -542,7 +519,7 @@ export class AccessibilitySignal { name: localize('accessibilitySignals.chatRequestSent', 'Chat Request Sent'), sound: Sound.chatRequestSent, legacySoundSettingsKey: 'audioCues.chatRequestSent', - legacyAnnouncementSettingsKey: AccessibilityAlertSettingId.ChatRequestSent, + legacyAnnouncementSettingsKey: 'accessibility.alert.chatRequestSent', announcementMessage: localize('accessibility.signals.chatRequestSent', 'Chat Request Sent'), settingsKey: 'accessibility.signals.chatRequestSent', }); @@ -565,7 +542,7 @@ export class AccessibilitySignal { name: localize('accessibilitySignals.progress', 'Progress'), sound: Sound.progress, legacySoundSettingsKey: 'audioCues.chatResponsePending', - legacyAnnouncementSettingsKey: AccessibilityAlertSettingId.Progress, + legacyAnnouncementSettingsKey: 'accessibility.alert.progress', announcementMessage: localize('accessibility.signals.progress', 'Progress'), settingsKey: 'accessibility.signals.progress' }); @@ -574,7 +551,7 @@ export class AccessibilitySignal { name: localize('accessibilitySignals.clear', 'Clear'), sound: Sound.clear, legacySoundSettingsKey: 'audioCues.clear', - legacyAnnouncementSettingsKey: AccessibilityAlertSettingId.Clear, + legacyAnnouncementSettingsKey: 'accessibility.alert.clear', announcementMessage: localize('accessibility.signals.clear', 'Clear'), settingsKey: 'accessibility.signals.clear' }); @@ -583,7 +560,7 @@ export class AccessibilitySignal { name: localize('accessibilitySignals.save', 'Save'), sound: Sound.save, legacySoundSettingsKey: 'audioCues.save', - legacyAnnouncementSettingsKey: AccessibilityAlertSettingId.Save, + legacyAnnouncementSettingsKey: 'accessibility.alert.save', announcementMessage: localize('accessibility.signals.save', 'Save'), settingsKey: 'accessibility.signals.save' }); @@ -592,7 +569,7 @@ export class AccessibilitySignal { name: localize('accessibilitySignals.format', 'Format'), sound: Sound.format, legacySoundSettingsKey: 'audioCues.format', - legacyAnnouncementSettingsKey: AccessibilityAlertSettingId.Format, + legacyAnnouncementSettingsKey: 'accessibility.alert.format', announcementMessage: localize('accessibility.signals.format', 'Format'), settingsKey: 'accessibility.signals.format' }); diff --git a/src/vs/workbench/contrib/accessibility/browser/accessibility.contribution.ts b/src/vs/workbench/contrib/accessibility/browser/accessibility.contribution.ts index ebd81e486052e..aa516a2853776 100644 --- a/src/vs/workbench/contrib/accessibility/browser/accessibility.contribution.ts +++ b/src/vs/workbench/contrib/accessibility/browser/accessibility.contribution.ts @@ -17,11 +17,9 @@ import { SaveAccessibilitySignalContribution } from 'vs/workbench/contrib/access import { CommentsAccessibilityHelpContribution } from 'vs/workbench/contrib/comments/browser/commentsAccessibility'; import { DiffEditorActiveAnnouncementContribution } from 'vs/workbench/contrib/accessibilitySignals/browser/openDiffEditorAnnouncement'; import { SpeechAccessibilitySignalContribution } from 'vs/workbench/contrib/speech/browser/speechAccessibilitySignal'; -import { registerAudioCueConfiguration } from 'vs/workbench/contrib/accessibility/browser/audioCueConfiguration'; import { AccessibleViewInformationService, IAccessibleViewInformationService } from 'vs/workbench/services/accessibility/common/accessibleViewInformationService'; registerAccessibilityConfiguration(); -registerAudioCueConfiguration(); registerSingleton(IAccessibleViewService, AccessibleViewService, InstantiationType.Delayed); registerSingleton(IAccessibleViewInformationService, AccessibleViewInformationService, InstantiationType.Delayed); diff --git a/src/vs/workbench/contrib/accessibility/browser/accessibilityConfiguration.ts b/src/vs/workbench/contrib/accessibility/browser/accessibilityConfiguration.ts index 478dc21bf4ead..30adaf6e8ddc5 100644 --- a/src/vs/workbench/contrib/accessibility/browser/accessibilityConfiguration.ts +++ b/src/vs/workbench/contrib/accessibility/browser/accessibilityConfiguration.ts @@ -8,7 +8,7 @@ import { ConfigurationScope, Extensions, IConfigurationNode, IConfigurationPrope import { Registry } from 'vs/platform/registry/common/platform'; import { RawContextKey } from 'vs/platform/contextkey/common/contextkey'; import { workbenchConfigurationNodeBase, Extensions as WorkbenchExtensions, IConfigurationMigrationRegistry, ConfigurationKeyValuePairs, ConfigurationMigration } from 'vs/workbench/common/configuration'; -import { AccessibilityAlertSettingId, AccessibilitySignal } from 'vs/platform/accessibilitySignal/browser/accessibilitySignalService'; +import { AccessibilitySignal } from 'vs/platform/accessibilitySignal/browser/accessibilitySignalService'; import { ISpeechService, SPEECH_LANGUAGES, SPEECH_LANGUAGE_CONFIG } from 'vs/workbench/contrib/speech/common/speechService'; import { Disposable } from 'vs/base/common/lifecycle'; import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; @@ -81,13 +81,6 @@ const baseVerbosityProperty: IConfigurationPropertySchema = { default: true, tags: ['accessibility'] }; -const markdownDeprecationMessage = localize('accessibility.announcement.deprecationMessage', "This setting is deprecated. Use the `signals` settings instead."); -const baseAlertProperty: IConfigurationPropertySchema = { - type: 'boolean', - default: true, - tags: ['accessibility'], - markdownDeprecationMessage -}; export const accessibilityConfigurationNodeBase = Object.freeze({ id: 'accessibility', @@ -189,99 +182,6 @@ const configuration: IConfigurationNode = { description: localize('verbosity.diffEditorActive', 'Indicate when a diff editor becomes the active editor.'), ...baseVerbosityProperty }, - [AccessibilityAlertSettingId.Save]: { - 'markdownDescription': localize('announcement.save', "Indicates when a file is saved. Also see {0}.", '`#audioCues.save#`'), - 'enum': ['userGesture', 'always', 'never'], - 'default': 'always', - 'enumDescriptions': [ - localize('announcement.save.userGesture', "Indicates when a file is saved via user gesture."), - localize('announcement.save.always', "Indicates whenever is a file is saved, including auto save."), - localize('announcement.save.never', "Never alerts.") - ], - tags: ['accessibility'], - markdownDeprecationMessage - }, - [AccessibilityAlertSettingId.Clear]: { - 'markdownDescription': localize('announcement.clear', "Indicates when a feature is cleared (for example, the terminal, Debug Console, or Output channel). Also see {0}.", '`#audioCues.clear#`'), - ...baseAlertProperty - }, - [AccessibilityAlertSettingId.Format]: { - 'markdownDescription': localize('announcement.format', "Indicates when a file or notebook cell is formatted. Also see {0}.", '`#audioCues.format#`'), - 'type': 'string', - 'enum': ['userGesture', 'always', 'never'], - 'default': 'always', - 'enumDescriptions': [ - localize('announcement.format.userGesture', "Indicates when a file is formatted via user gesture."), - localize('announcement.format.always', "Indicates whenever is a file is formatted, including auto save, on cell execution, and more."), - localize('announcement.format.never', "Never alerts.") - ], - tags: ['accessibility'], - markdownDeprecationMessage - }, - [AccessibilityAlertSettingId.Breakpoint]: { - 'markdownDescription': localize('announcement.breakpoint', "Indicates when the debugger breaks. Also see {0}.", '`#audioCues.onDebugBreak#`'), - ...baseAlertProperty - }, - [AccessibilityAlertSettingId.Error]: { - 'markdownDescription': localize('announcement.error', "Indicates when the active line has an error. Also see {0}.", '`#audioCues.lineHasError#`'), - ...baseAlertProperty - }, - [AccessibilityAlertSettingId.Warning]: { - 'markdownDescription': localize('announcement.warning', "Indicates when the active line has a warning. Also see {0}.", '`#audioCues.lineHasWarning#`'), - ...baseAlertProperty - }, - [AccessibilityAlertSettingId.FoldedArea]: { - 'markdownDescription': localize('announcement.foldedArea', "Indicates when the active line has a folded area that can be unfolded. Also see {0}.", '`#audioCues.lineHasFoldedArea#`'), - ...baseAlertProperty - }, - [AccessibilityAlertSettingId.TerminalQuickFix]: { - 'markdownDescription': localize('announcement.terminalQuickFix', "Indicates when there is an available terminal quick fix. Also see {0}.", '`#audioCues.terminalQuickFix#`'), - ...baseAlertProperty - }, - [AccessibilityAlertSettingId.TerminalBell]: { - 'markdownDescription': localize('announcement.terminalBell', "Indicates when the terminal bell is activated."), - ...baseAlertProperty - }, - [AccessibilityAlertSettingId.TerminalCommandFailed]: { - 'markdownDescription': localize('announcement.terminalCommandFailed', "Indicates when a terminal command fails (non-zero exit code). Also see {0}.", '`#audioCues.terminalCommandFailed#`'), - ...baseAlertProperty - }, - [AccessibilityAlertSettingId.TaskFailed]: { - 'markdownDescription': localize('announcement.taskFailed', "Indicates when a task fails (non-zero exit code). Also see {0}.", '`#audioCues.taskFailed#`'), - ...baseAlertProperty - }, - [AccessibilityAlertSettingId.TaskCompleted]: { - 'markdownDescription': localize('announcement.taskCompleted', "Indicates when a task completes successfully (zero exit code). Also see {0}.", '`#audioCues.taskCompleted#`'), - ...baseAlertProperty - }, - [AccessibilityAlertSettingId.ChatRequestSent]: { - 'markdownDescription': localize('announcement.chatRequestSent', "Indicates when a chat request is sent. Also see {0}.", '`#audioCues.chatRequestSent#`'), - ...baseAlertProperty - }, - [AccessibilityAlertSettingId.Progress]: { - 'markdownDescription': localize('announcement.progress', "Indicates when a chat response is pending. Also see {0}.", '`#audioCues.chatResponsePending#`'), - ...baseAlertProperty - }, - [AccessibilityAlertSettingId.NoInlayHints]: { - 'markdownDescription': localize('announcement.noInlayHints', "Indicates when there are no inlay hints. Also see {0}.", '`#audioCues.noInlayHints#`'), - ...baseAlertProperty - }, - [AccessibilityAlertSettingId.LineHasBreakpoint]: { - 'markdownDescription': localize('announcement.lineHasBreakpoint', "Indicates when on a line with a breakpoint. Also see {0}.", '`#audioCues.lineHasBreakpoint#`'), - ...baseAlertProperty - }, - [AccessibilityAlertSettingId.NotebookCellCompleted]: { - 'markdownDescription': localize('announcement.notebookCellCompleted', "Indicates when a notebook cell completes successfully. Also see {0}.", '`#audioCues.notebookCellCompleted#`'), - ...baseAlertProperty - }, - [AccessibilityAlertSettingId.NotebookCellFailed]: { - 'markdownDescription': localize('announcement.notebookCellFailed', "Indicates when a notebook cell fails. Also see {0}.", '`#audioCues.notebookCellFailed#`'), - ...baseAlertProperty - }, - [AccessibilityAlertSettingId.OnDebugBreak]: { - 'markdownDescription': localize('announcement.onDebugBreak', "Indicates when the debugger breaks. Also see {0}.", '`#audioCues.onDebugBreak#`'), - ...baseAlertProperty - }, [AccessibilityWorkbenchSettingId.AccessibleViewCloseOnKeyPress]: { markdownDescription: localize('terminal.integrated.accessibleView.closeOnKeyPress', "On keypress, close the Accessible View and focus the element from which it was invoked."), type: 'boolean', @@ -645,9 +545,9 @@ const configuration: IConfigurationNode = { 'enum': ['userGesture', 'always', 'never'], 'default': 'never', 'enumDescriptions': [ - localize('accessibility.signals.save.sound.userGesture', "Plays the audio cue when a user explicitly saves a file."), - localize('accessibility.signals.save.sound.always', "Plays the audio cue whenever a file is saved, including auto save."), - localize('accessibility.signals.save.sound.never', "Never plays the audio cue.") + localize('accessibility.signals.save.sound.userGesture', "Plays the sound when a user explicitly saves a file."), + localize('accessibility.signals.save.sound.always', "Plays the sound whenever a file is saved, including auto save."), + localize('accessibility.signals.save.sound.never', "Never plays the sound.") ], }, 'announcement': { @@ -658,7 +558,7 @@ const configuration: IConfigurationNode = { 'enumDescriptions': [ localize('accessibility.signals.save.announcement.userGesture', "Announces when a user explicitly saves a file."), localize('accessibility.signals.save.announcement.always', "Announces whenever a file is saved, including auto save."), - localize('accessibility.signals.save.announcement.never', "Never plays the audio cue.") + localize('accessibility.signals.save.announcement.never', "Never plays the announcement.") ], }, }, @@ -679,9 +579,9 @@ const configuration: IConfigurationNode = { 'enum': ['userGesture', 'always', 'never'], 'default': 'never', 'enumDescriptions': [ - localize('accessibility.signals.format.userGesture', "Plays the audio cue when a user explicitly formats a file."), - localize('accessibility.signals.format.always', "Plays the audio cue whenever a file is formatted, including if it is set to format on save, type, or, paste, or run of a cell."), - localize('accessibility.signals.format.never', "Never plays the audio cue.") + localize('accessibility.signals.format.userGesture', "Plays the sound when a user explicitly formats a file."), + localize('accessibility.signals.format.always', "Plays the sound whenever a file is formatted, including if it is set to format on save, type, or, paste, or run of a cell."), + localize('accessibility.signals.format.never', "Never plays the sound.") ], }, 'announcement': { diff --git a/src/vs/workbench/contrib/accessibility/browser/audioCueConfiguration.ts b/src/vs/workbench/contrib/accessibility/browser/audioCueConfiguration.ts deleted file mode 100644 index a1114ff859cf1..0000000000000 --- a/src/vs/workbench/contrib/accessibility/browser/audioCueConfiguration.ts +++ /dev/null @@ -1,163 +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 { localize } from 'vs/nls'; -import { Extensions as ConfigurationExtensions, ConfigurationScope, IConfigurationPropertySchema, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry'; -import { Registry } from 'vs/platform/registry/common/platform'; - -export const audioCueFeatureBase: IConfigurationPropertySchema = { - 'type': 'string', - 'enum': ['auto', 'on', 'off'], - 'default': 'auto', - 'enumDescriptions': [ - localize('audioCues.enabled.auto', "Enable audio cue when a screen reader is attached."), - localize('audioCues.enabled.on', "Enable audio cue."), - localize('audioCues.enabled.off', "Disable audio cue.") - ], - tags: ['accessibility'], -}; -const markdownDeprecationMessage = localize('audioCues.enabled.deprecated', "This setting is deprecated. Use `signals` settings instead."); -const soundDeprecatedFeatureBase: IConfigurationPropertySchema = { - ...audioCueFeatureBase, - markdownDeprecationMessage -}; -export function registerAudioCueConfiguration() { - Registry.as(ConfigurationExtensions.Configuration).registerConfiguration({ - scope: ConfigurationScope.RESOURCE, - 'properties': { - 'audioCues.enabled': { - markdownDeprecationMessage: 'Deprecated. Use the specific setting for each audio cue instead (`audioCues.*`).', - tags: ['accessibility'] - }, - 'audioCues.volume': { - markdownDeprecationMessage: 'Deprecated. Use `accessibility.signals.sounds.volume` instead.', - tags: ['accessibility'] - }, - 'audioCues.debouncePositionChanges': { - 'description': localize('audioCues.debouncePositionChanges', "Whether or not position changes should be debounced"), - 'type': 'boolean', - 'default': false, - tags: ['accessibility'], - 'markdownDeprecationMessage': localize('audioCues.debouncePositionChangesDeprecated', 'This setting is deprecated, instead use the `signals.debouncePositionChanges` setting.') - }, - 'audioCues.lineHasBreakpoint': { - 'description': localize('audioCues.lineHasBreakpoint', "Plays a sound when the active line has a breakpoint."), - ...soundDeprecatedFeatureBase - }, - 'audioCues.lineHasInlineSuggestion': { - 'description': localize('audioCues.lineHasInlineSuggestion', "Plays a sound when the active line has an inline suggestion."), - ...soundDeprecatedFeatureBase - }, - 'audioCues.lineHasError': { - 'description': localize('audioCues.lineHasError', "Plays a sound when the active line has an error."), - ...soundDeprecatedFeatureBase, - }, - 'audioCues.lineHasFoldedArea': { - 'description': localize('audioCues.lineHasFoldedArea', "Plays a sound when the active line has a folded area that can be unfolded."), - ...soundDeprecatedFeatureBase, - }, - 'audioCues.lineHasWarning': { - 'description': localize('audioCues.lineHasWarning', "Plays a sound when the active line has a warning."), - ...soundDeprecatedFeatureBase, - default: 'off', - }, - 'audioCues.onDebugBreak': { - 'description': localize('audioCues.onDebugBreak', "Plays a sound when the debugger stopped on a breakpoint."), - ...soundDeprecatedFeatureBase, - }, - 'audioCues.noInlayHints': { - 'description': localize('audioCues.noInlayHints', "Plays a sound when trying to read a line with inlay hints that has no inlay hints."), - ...soundDeprecatedFeatureBase, - }, - 'audioCues.taskCompleted': { - 'description': localize('audioCues.taskCompleted', "Plays a sound when a task is completed."), - ...soundDeprecatedFeatureBase, - }, - 'audioCues.taskFailed': { - 'description': localize('audioCues.taskFailed', "Plays a sound when a task fails (non-zero exit code)."), - ...soundDeprecatedFeatureBase, - }, - 'audioCues.terminalCommandFailed': { - 'description': localize('audioCues.terminalCommandFailed', "Plays a sound when a terminal command fails (non-zero exit code)."), - ...soundDeprecatedFeatureBase, - }, - 'audioCues.terminalQuickFix': { - 'description': localize('audioCues.terminalQuickFix', "Plays a sound when terminal Quick Fixes are available."), - ...soundDeprecatedFeatureBase, - }, - 'audioCues.terminalBell': { - 'description': localize('audioCues.terminalBell', "Plays a sound when the terminal bell is ringing."), - ...soundDeprecatedFeatureBase, - default: 'on' - }, - 'audioCues.diffLineInserted': { - 'description': localize('audioCues.diffLineInserted', "Plays a sound when the focus moves to an inserted line in Accessible Diff Viewer mode or to the next/previous change."), - ...soundDeprecatedFeatureBase, - }, - 'audioCues.diffLineDeleted': { - 'description': localize('audioCues.diffLineDeleted', "Plays a sound when the focus moves to a deleted line in Accessible Diff Viewer mode or to the next/previous change."), - ...soundDeprecatedFeatureBase, - }, - 'audioCues.diffLineModified': { - 'description': localize('audioCues.diffLineModified', "Plays a sound when the focus moves to a modified line in Accessible Diff Viewer mode or to the next/previous change."), - ...soundDeprecatedFeatureBase, - }, - 'audioCues.notebookCellCompleted': { - 'description': localize('audioCues.notebookCellCompleted', "Plays a sound when a notebook cell execution is successfully completed."), - ...soundDeprecatedFeatureBase, - }, - 'audioCues.notebookCellFailed': { - 'description': localize('audioCues.notebookCellFailed', "Plays a sound when a notebook cell execution fails."), - ...soundDeprecatedFeatureBase, - }, - 'audioCues.chatRequestSent': { - 'description': localize('audioCues.chatRequestSent', "Plays a sound when a chat request is made."), - ...soundDeprecatedFeatureBase, - default: 'off' - }, - 'audioCues.chatResponsePending': { - 'description': localize('audioCues.chatResponsePending', "Plays a sound on loop while the response is pending."), - ...soundDeprecatedFeatureBase, - default: 'auto' - }, - 'audioCues.chatResponseReceived': { - 'description': localize('audioCues.chatResponseReceived', "Plays a sound on loop while the response has been received."), - ...soundDeprecatedFeatureBase, - default: 'off' - }, - 'audioCues.clear': { - 'description': localize('audioCues.clear', "Plays a sound when a feature is cleared (for example, the terminal, Debug Console, or Output channel). When this is disabled, an ARIA alert will announce 'Cleared'."), - ...soundDeprecatedFeatureBase, - default: 'off' - }, - 'audioCues.save': { - 'markdownDescription': localize('audioCues.save', "Plays a sound when a file is saved. Also see {0}", '`#accessibility.alert.save#`'), - 'type': 'string', - 'enum': ['userGesture', 'always', 'never'], - 'default': 'never', - 'enumDescriptions': [ - localize('audioCues.save.userGesture', "Plays the audio cue when a user explicitly saves a file."), - localize('audioCues.save.always', "Plays the audio cue whenever a file is saved, including auto save."), - localize('audioCues.save.never', "Never plays the audio cue.") - ], - tags: ['accessibility'], - markdownDeprecationMessage - }, - 'audioCues.format': { - 'markdownDescription': localize('audioCues.format', "Plays a sound when a file or notebook is formatted. Also see {0}", '`#accessibility.alert.format#`'), - 'type': 'string', - 'enum': ['userGesture', 'always', 'never'], - 'default': 'never', - 'enumDescriptions': [ - localize('audioCues.format.userGesture', "Plays the audio cue when a user explicitly formats a file."), - localize('audioCues.format.always', "Plays the audio cue whenever a file is formatted, including if it is set to format on save, type, or, paste, or run of a cell."), - localize('audioCues.format.never', "Never plays the audio cue.") - ], - tags: ['accessibility'], - markdownDeprecationMessage - }, - }, - }); -} From 676d4d8492c92c54bc690dedc2832af82e6f063c Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Fri, 26 Apr 2024 10:12:01 -0700 Subject: [PATCH 026/104] Clean up suggestions, move all triggers to client --- .../browser/media/shellIntegration.ps1 | 29 --------------- .../suggest/browser/terminalSuggestAddon.ts | 37 +++++++++---------- 2 files changed, 17 insertions(+), 49 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/browser/media/shellIntegration.ps1 b/src/vs/workbench/contrib/terminal/browser/media/shellIntegration.ps1 index 303859ab04bb7..a7b9c69cfd748 100644 --- a/src/vs/workbench/contrib/terminal/browser/media/shellIntegration.ps1 +++ b/src/vs/workbench/contrib/terminal/browser/media/shellIntegration.ps1 @@ -157,7 +157,6 @@ function Set-MappedKeyHandler { } } -$Global:__VSCodeHaltCompletions = $false function Set-MappedKeyHandlers { Set-MappedKeyHandler -Chord Ctrl+Spacebar -Sequence 'F12,a' Set-MappedKeyHandler -Chord Alt+Spacebar -Sequence 'F12,b' @@ -173,34 +172,6 @@ function Set-MappedKeyHandlers { Send-Completions } - # Suggest trigger characters - # Set-PSReadLineKeyHandler -Chord "-" -ScriptBlock { - # [Microsoft.PowerShell.PSConsoleReadLine]::Insert("-") - # if (!$Global:__VSCodeHaltCompletions) { - # Send-Completions - # } - # } - # Set-PSReadLineKeyHandler -Chord "\" -ScriptBlock { - # [Microsoft.PowerShell.PSConsoleReadLine]::Insert("\") - # if (!$Global:__VSCodeHaltCompletions) { - # Send-Completions - # } - # } - # Set-PSReadLineKeyHandler -Chord "/" -ScriptBlock { - # [Microsoft.PowerShell.PSConsoleReadLine]::Insert("/") - # if (!$Global:__VSCodeHaltCompletions) { - # Send-Completions - # } - # } - - Set-PSReadLineKeyHandler -Chord 'F12,y' -ScriptBlock { - $Global:__VSCodeHaltCompletions = $true - } - - Set-PSReadLineKeyHandler -Chord 'F12,z' -ScriptBlock { - $Global:__VSCodeHaltCompletions = $false - } - # TODO: When does this invalidate? Installing a new module could add new commands # Commands are expensive to complete and send over, do this ones for the empty string so we # don't need to do it each time the user requests. diff --git a/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon.ts b/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon.ts index 91a6a932dd7a9..ecf1ea09c0e3e 100644 --- a/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon.ts +++ b/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon.ts @@ -19,10 +19,12 @@ import { activeContrastBorder } from 'vs/platform/theme/common/colorRegistry'; import { ISuggestController } from 'vs/workbench/contrib/terminal/browser/terminal'; import { TerminalStorageKeys } from 'vs/workbench/contrib/terminal/common/terminalStorageKeys'; import type { ITerminalAddon, Terminal } from '@xterm/xterm'; + import { getListStyles } from 'vs/platform/theme/browser/defaultStyles'; import { TerminalCapability, type ITerminalCapabilityStore } from 'vs/platform/terminal/common/capabilities/capabilities'; import type { IPromptInputModel, IPromptInputModelState } from 'vs/platform/terminal/common/capabilities/commandDetection/promptInputModel'; import { ShellIntegrationOscPs } from 'vs/platform/terminal/common/xterm/shellIntegrationAddon'; +import type { IXtermCore } from 'vs/workbench/contrib/terminal/browser/xterm-private'; const enum VSCodeOscPt { Completions = 'Completions', @@ -135,21 +137,26 @@ export class SuggestAddon extends Disposable implements ITerminalAddon, ISuggest this._screen = screen; } + private _requestCompletions(): void { + // TODO: Debounce? Prevent this flooding the channel + this._onAcceptedCompletion.fire('\x1b[24~e'); + } + private _sync(promptInputState: IPromptInputModelState): void { if (!this._terminalSuggestWidgetVisibleContextKey.get()) { // If input has been added if (!this._mostRecentPromptInputState || promptInputState.cursorIndex > this._mostRecentPromptInputState.cursorIndex) { // Quick suggestions if (promptInputState.cursorIndex === 1 || promptInputState.value.substring(0, promptInputState.cursorIndex).match(/\s[^\s]$/)) { - // TODO: Allow the user to configure when completions are triggered - this is equivalent to editor.quickSuggestions - // TODO: Debounce? Prevent this flooding the channel - this._onAcceptedCompletion.fire('\x1b[24~e'); + // TODO: Allow the user to configure terminal quickSuggestions + this._requestCompletions(); } // Trigger characters const lastChar = promptInputState.value.at(promptInputState.cursorIndex - 1); if (lastChar?.match(/[\\\/\-]/)) { - this._onAcceptedCompletion.fire('\x1b[24~e'); + // TODO: Allow the user to configure terminal suggestOnTriggerCharacters + this._requestCompletions(); } } } @@ -173,23 +180,15 @@ export class SuggestAddon extends Disposable implements ITerminalAddon, ISuggest if (this._terminalSuggestWidgetVisibleContextKey.get()) { const inputBeforeCursor = this._currentPromptInputState.value.substring(0, this._currentPromptInputState.cursorIndex); this._cursorIndexDelta = this._currentPromptInputState.cursorIndex - this._initialPromptInputState.cursorIndex; - - console.log('setLineContext', { - inputBeforeCursor, - cursorIndexDelta: this._cursorIndexDelta - }); this._suggestWidget.setLineContext(new LineContext(inputBeforeCursor, this._cursorIndexDelta)); } // Hide and clear model if there are no more items if (!this._suggestWidget.hasCompletions()) { this.hideSuggestWidget(); - // TODO: Don't request every time; refine completions - // this._onAcceptedCompletion.fire('\x1b[24~e'); return; } - // TODO: Expose on xterm.js const dimensions = this._getTerminalDimensions(); if (!dimensions.width || !dimensions.height) { return; @@ -235,8 +234,8 @@ export class SuggestAddon extends Disposable implements ITerminalAddon, ISuggest return; } - let replacementIndex = 0; //args.length === 0 ? 0 : parseInt(args[0]); - let replacementLength = this._promptInputModel.cursorIndex; //args.length === 0 ? 0 : parseInt(args[1]); + let replacementIndex = 0; + let replacementLength = this._promptInputModel.cursorIndex; const payload = data.slice(command.length + args[0].length + args[1].length + args[2].length + 4/*semi-colons*/); let completionList: IPwshCompletion[] | IPwshCompletion = args.length === 0 || payload.length === 0 ? [] : JSON.parse(payload); @@ -267,6 +266,7 @@ export class SuggestAddon extends Disposable implements ITerminalAddon, ISuggest this._handleCompletionModel(model); } + // TODO: These aren't persisted across reloads private _cachedPwshCommands: Set = new Set(); private _handleCompletionsPwshCommandsSequence(terminal: Terminal, data: string, command: string, args: string[]): void { const type = args[0]; @@ -387,9 +387,10 @@ export class SuggestAddon extends Disposable implements ITerminalAddon, ISuggest } private _getTerminalDimensions(): { width: number; height: number } { + const cssCellDims = (this._terminal as any as { _core: IXtermCore })._core._renderService.dimensions.css.cell; return { - width: (this._terminal as any)._core._renderService.dimensions.css.cell.width, - height: (this._terminal as any)._core._renderService.dimensions.css.cell.height, + width: cssCellDims.width, + height: cssCellDims.height, }; } @@ -481,8 +482,6 @@ export class SuggestAddon extends Disposable implements ITerminalAddon, ISuggest // Send the completion this._onAcceptedCompletion.fire([ - // Disable suggestions - '\x1b[24~y', // Backspace to remove all additional input '\x7F'.repeat(additionalInput.length), // Backspace to remove left side of completion @@ -491,8 +490,6 @@ export class SuggestAddon extends Disposable implements ITerminalAddon, ISuggest finalCompletionLeftSide, // Write the completion finalCompletionRightSide, - // Enable suggestions - '\x1b[24~z', ].join('')); this.hideSuggestWidget(); From 6994e3c9c3ad8feda91d87f16c0b4b9a6ff20367 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Fri, 26 Apr 2024 10:13:20 -0700 Subject: [PATCH 027/104] More polish --- .../browser/media/shellIntegration.ps1 | 27 +------------------ 1 file changed, 1 insertion(+), 26 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/browser/media/shellIntegration.ps1 b/src/vs/workbench/contrib/terminal/browser/media/shellIntegration.ps1 index a7b9c69cfd748..eafe56abbbab1 100644 --- a/src/vs/workbench/contrib/terminal/browser/media/shellIntegration.ps1 +++ b/src/vs/workbench/contrib/terminal/browser/media/shellIntegration.ps1 @@ -184,9 +184,6 @@ function Set-MappedKeyHandlers { function Send-Completions { $commandLine = "" $cursorIndex = 0 - # TODO: Since fuzzy matching exists, should completions be provided only for character after the - # last space and then filter on the client side? That would let you trigger ctrl+space - # anywhere on a word and have full completions available [Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$commandLine, [ref]$cursorIndex) $completionPrefix = $commandLine @@ -205,12 +202,7 @@ function Send-Completions { # If there is no space, get completions using CompletionCompleters as it gives us more # control and works on the empty string else { - # $completions = TabExpansion2 -inputScript $completionPrefix -cursorColumn $cursorIndex - # if ($null -ne $completions.CompletionMatches) { - # $result += ";$($completions.ReplacementIndex);$($completions.ReplacementLength);$($cursorIndex);" - # $result += $completions.CompletionMatches | ConvertTo-Json -Compress - # } - # Get and send completions, note that CompleteCommand isn't included here as it's expensive + # Note that CompleteCommand isn't included here as it's expensive $completions = $( ([System.Management.Automation.CompletionCompleters]::CompleteFilename($completionPrefix)); ([System.Management.Automation.CompletionCompleters]::CompleteVariable($completionPrefix)); @@ -222,23 +214,6 @@ function Send-Completions { $result += ";0;$($completionPrefix.Length);$($completionPrefix.Length);[]" } } - # } else { - # # TODO: Consolidate this case with the above - # # TODO: Try use this approach after the last whitespace for everything so intellisense is always consistent - - # # Special case when the prefix is empty since TabExpansion2 doesn't handle it - # if ($completionPrefix.Length -eq 0) { - # # Get and send completions - # $completions = $( - # ([System.Management.Automation.CompletionCompleters]::CompleteFilename('')); - # ([System.Management.Automation.CompletionCompleters]::CompleteVariable('')); - # ) - # if ($null -ne $completions) { - # $result += ";0;0;0;" - # $result += $completions | ConvertTo-Json -Compress - # } - # } - # } # End completions sequence $result += "`a" From 73f9a3d13312ad8089071654704fb7b46bcbf538 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Fri, 26 Apr 2024 10:28:08 -0700 Subject: [PATCH 028/104] Improve comments --- .../contrib/terminal/browser/media/shellIntegration.ps1 | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/browser/media/shellIntegration.ps1 b/src/vs/workbench/contrib/terminal/browser/media/shellIntegration.ps1 index eafe56abbbab1..b48ccd4d75c14 100644 --- a/src/vs/workbench/contrib/terminal/browser/media/shellIntegration.ps1 +++ b/src/vs/workbench/contrib/terminal/browser/media/shellIntegration.ps1 @@ -172,9 +172,10 @@ function Set-MappedKeyHandlers { Send-Completions } - # TODO: When does this invalidate? Installing a new module could add new commands - # Commands are expensive to complete and send over, do this ones for the empty string so we - # don't need to do it each time the user requests. + # TODO: When does this invalidate? Installing a new module could add new commands. We could expose a command to update? + # Commands are expensive to complete and send over, do this once for the empty string so we + # don't need to do it each time the user requests. Additionally we also want to do filtering + # and ranking on the client side with the full list of results. $result = "$([char]0x1b)]633;CompletionsPwshCommands;commands;" $result += [System.Management.Automation.CompletionCompleters]::CompleteCommand('') | ConvertTo-Json -Compress Write-Host -NoNewLine $result From c5b32bb6e942d451b78239acc2073e383da11ebf Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Fri, 26 Apr 2024 10:29:15 -0700 Subject: [PATCH 029/104] Add another idea --- .../contrib/terminal/browser/media/shellIntegration.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/terminal/browser/media/shellIntegration.ps1 b/src/vs/workbench/contrib/terminal/browser/media/shellIntegration.ps1 index b48ccd4d75c14..f2f50c467177b 100644 --- a/src/vs/workbench/contrib/terminal/browser/media/shellIntegration.ps1 +++ b/src/vs/workbench/contrib/terminal/browser/media/shellIntegration.ps1 @@ -172,7 +172,7 @@ function Set-MappedKeyHandlers { Send-Completions } - # TODO: When does this invalidate? Installing a new module could add new commands. We could expose a command to update? + # TODO: When does this invalidate? Installing a new module could add new commands. We could expose a command to update? Track `(Get-Module).Count`? # Commands are expensive to complete and send over, do this once for the empty string so we # don't need to do it each time the user requests. Additionally we also want to do filtering # and ranking on the client side with the full list of results. From caf118533f2d95e0c91264efce1e9d7b8c862083 Mon Sep 17 00:00:00 2001 From: Raymond Zhao <7199958+rzhao271@users.noreply.github.com> Date: Fri, 26 Apr 2024 10:31:54 -0700 Subject: [PATCH 030/104] chore: add CodeQL params to improve perf (#211392) --- build/azure-pipelines/product-build.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/build/azure-pipelines/product-build.yml b/build/azure-pipelines/product-build.yml index dbc9ccb946bb3..0027a774b3570 100644 --- a/build/azure-pipelines/product-build.yml +++ b/build/azure-pipelines/product-build.yml @@ -181,6 +181,10 @@ extends: notificationAliases: ['monacotools@microsoft.com'] validateToolOutput: None allTools: true + codeql: + compiled: + enabled: true + runSourceLanguagesInSourceAnalysis: true credscan: suppressionsFile: $(Build.SourcesDirectory)/build/azure-pipelines/config/CredScanSuppressions.json eslint: From 578fa6f66131525aca3f3463b038bf2b3a237be0 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Fri, 26 Apr 2024 10:33:41 -0700 Subject: [PATCH 031/104] Remove canvas addon from sticky scroll --- .../browser/terminalStickyScrollOverlay.ts | 47 +------------------ 1 file changed, 1 insertion(+), 46 deletions(-) diff --git a/src/vs/workbench/contrib/terminalContrib/stickyScroll/browser/terminalStickyScrollOverlay.ts b/src/vs/workbench/contrib/terminalContrib/stickyScroll/browser/terminalStickyScrollOverlay.ts index eac420466bbf8..a3398afe76c18 100644 --- a/src/vs/workbench/contrib/terminalContrib/stickyScroll/browser/terminalStickyScrollOverlay.ts +++ b/src/vs/workbench/contrib/terminalContrib/stickyScroll/browser/terminalStickyScrollOverlay.ts @@ -2,12 +2,11 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import type { CanvasAddon as CanvasAddonType } from '@xterm/addon-canvas'; + import type { SerializeAddon as SerializeAddonType } from '@xterm/addon-serialize'; import type { IBufferLine, IMarker, ITerminalOptions, ITheme, Terminal as RawXtermTerminal, Terminal as XTermTerminal } from '@xterm/xterm'; import { importAMDNodeModule } from 'vs/amdX'; import { $, addDisposableListener, addStandardDisposableListener, getWindow } from 'vs/base/browser/dom'; -import { CancelablePromise, createCancelablePromise } from 'vs/base/common/async'; import { memoize, throttle } from 'vs/base/common/decorators'; import { Event } from 'vs/base/common/event'; import { Disposable, MutableDisposable, combinedDisposable, toDisposable } from 'vs/base/common/lifecycle'; @@ -48,9 +47,6 @@ export class TerminalStickyScrollOverlay extends Disposable { private _stickyScrollOverlay?: RawXtermTerminal; private _serializeAddon?: SerializeAddonType; - private readonly _canvasAddon = this._register(new MutableDisposable()); - private _pendingCanvasAddon?: CancelablePromise; - private _element?: HTMLElement; private _currentStickyCommand?: ITerminalCommand | ICurrentPartialCommand; private _currentContent?: string; @@ -124,8 +120,6 @@ export class TerminalStickyScrollOverlay extends Disposable { // Trigger a render as the serialize addon is required to render this._refresh(); }); - - this._syncGpuAccelerationState(); }); } @@ -177,9 +171,6 @@ export class TerminalStickyScrollOverlay extends Disposable { private _setVisible(isVisible: boolean) { if (isVisible) { this._ensureElement(); - // The GPU acceleration state may be changes at any time and there is no event to listen - // to currently. - this._syncGpuAccelerationState(); } this._element?.classList.toggle(CssClasses.Visible, isVisible); } @@ -419,36 +410,6 @@ export class TerminalStickyScrollOverlay extends Disposable { } this._stickyScrollOverlay.resize(this._xterm.raw.cols, this._stickyScrollOverlay.rows); this._stickyScrollOverlay.options = this._getOptions(); - this._syncGpuAccelerationState(); - } - - private _syncGpuAccelerationState() { - if (!this._stickyScrollOverlay) { - return; - } - const overlay = this._stickyScrollOverlay; - - // The Webgl renderer isn't used here as there are a limited number of webgl contexts - // available within a given page. This is a single row that isn't rendered too often so the - // performance isn't as important - if (this._xterm.isGpuAccelerated) { - if (!this._canvasAddon.value && !this._pendingCanvasAddon) { - this._pendingCanvasAddon = createCancelablePromise(async token => { - const CanvasAddon = await this._getCanvasAddonConstructor(); - if (!token.isCancellationRequested && !this._store.isDisposed) { - this._canvasAddon.value = new CanvasAddon(); - if (this._canvasAddon.value) { // The MutableDisposable could be disposed - overlay.loadAddon(this._canvasAddon.value); - } - } - this._pendingCanvasAddon = undefined; - }); - } - } else { - this._canvasAddon.clear(); - this._pendingCanvasAddon?.cancel(); - this._pendingCanvasAddon = undefined; - } } private _getOptions(): ITerminalOptions { @@ -486,12 +447,6 @@ export class TerminalStickyScrollOverlay extends Disposable { }; } - @memoize - private async _getCanvasAddonConstructor(): Promise { - const m = await importAMDNodeModule('@xterm/addon-canvas', 'lib/xterm-addon-canvas.js'); - return m.CanvasAddon; - } - @memoize private async _getSerializeAddonConstructor(): Promise { const m = await importAMDNodeModule('@xterm/addon-serialize', 'lib/addon-serialize.js'); From febfca13374a013bd2ae49fbc8e35135baadf774 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Fri, 26 Apr 2024 10:34:28 -0700 Subject: [PATCH 032/104] Remove canvas references in build/lint --- .eslintrc.json | 1 - build/.webignore | 3 --- src/bootstrap-window.js | 1 - 3 files changed, 5 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index 19d2c1e06a589..83e5bf34dae04 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -671,7 +671,6 @@ "vscode-regexpp", "vscode-textmate", "worker_threads", - "@xterm/addon-canvas", "@xterm/addon-image", "@xterm/addon-search", "@xterm/addon-serialize", diff --git a/build/.webignore b/build/.webignore index 0145e3b7da4d9..88fe96f5cc16d 100644 --- a/build/.webignore +++ b/build/.webignore @@ -20,9 +20,6 @@ vscode-textmate/webpack.config.js @xterm/xterm/src/** -@xterm/addon-canvas/src/** -@xterm/addon-canvas/out/** - @xterm/addon-image/src/** @xterm/addon-image/out/** diff --git a/src/bootstrap-window.js b/src/bootstrap-window.js index 85409cc5a212d..fa3bc5eb839dc 100644 --- a/src/bootstrap-window.js +++ b/src/bootstrap-window.js @@ -124,7 +124,6 @@ 'vscode-oniguruma': `${baseNodeModulesPath}/vscode-oniguruma/release/main.js`, 'vsda': `${baseNodeModulesPath}/vsda/index.js`, '@xterm/xterm': `${baseNodeModulesPath}/@xterm/xterm/lib/xterm.js`, - '@xterm/addon-canvas': `${baseNodeModulesPath}/@xterm/addon-canvas/lib/addon-canvas.js`, '@xterm/addon-image': `${baseNodeModulesPath}/@xterm/addon-image/lib/addon-image.js`, '@xterm/addon-search': `${baseNodeModulesPath}/@xterm/addon-search/lib/addon-search.js`, '@xterm/addon-serialize': `${baseNodeModulesPath}/@xterm/addon-serialize/lib/addon-serialize.js`, From 5f3f4e927b0a9c38ee5555b2c4d300b13ff5cc9b Mon Sep 17 00:00:00 2001 From: Megan Rogge Date: Fri, 26 Apr 2024 12:17:19 -0700 Subject: [PATCH 033/104] tweak accessibility signal settings wording to include audio cue, alert, and announcement descriptors (#211476) --- .../browser/accessibilityConfiguration.ts | 94 +++++++++---------- 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/src/vs/workbench/contrib/accessibility/browser/accessibilityConfiguration.ts b/src/vs/workbench/contrib/accessibility/browser/accessibilityConfiguration.ts index 30adaf6e8ddc5..8bd810cfcb4f3 100644 --- a/src/vs/workbench/contrib/accessibility/browser/accessibilityConfiguration.ts +++ b/src/vs/workbench/contrib/accessibility/browser/accessibilityConfiguration.ts @@ -203,21 +203,21 @@ const configuration: IConfigurationNode = { }, 'accessibility.signals.lineHasBreakpoint': { ...signalFeatureBase, - 'description': localize('accessibility.signals.lineHasBreakpoint', "Plays a signal when the active line has a breakpoint."), + 'description': localize('accessibility.signals.lineHasBreakpoint', "Plays a signal - sound (audio cue) and/or announcement (alert) - when the active line has a breakpoint."), 'properties': { 'sound': { 'description': localize('accessibility.signals.lineHasBreakpoint.sound', "Plays a sound when the active line has a breakpoint."), ...soundFeatureBase }, 'announcement': { - 'description': localize('accessibility.signals.lineHasBreakpoint.announcement', "Indicates when the active line has a breakpoint."), + 'description': localize('accessibility.signals.lineHasBreakpoint.announcement', "Announces when the active line has a breakpoint."), ...announcementFeatureBase }, }, }, 'accessibility.signals.lineHasInlineSuggestion': { ...defaultNoAnnouncement, - 'description': localize('accessibility.signals.lineHasInlineSuggestion', "Indicates when the active line has an inline suggestion."), + 'description': localize('accessibility.signals.lineHasInlineSuggestion', "Plays a sound / audio cue when the active line has an inline suggestion."), 'properties': { 'sound': { 'description': localize('accessibility.signals.lineHasInlineSuggestion.sound', "Plays a sound when the active line has an inline suggestion."), @@ -228,14 +228,14 @@ const configuration: IConfigurationNode = { }, 'accessibility.signals.lineHasError': { ...signalFeatureBase, - 'description': localize('accessibility.signals.lineHasError', "Indicates when the active line has an error."), + 'description': localize('accessibility.signals.lineHasError', "Plays a signal - sound (audio cue) and/or announcement (alert) - when the active line has an error."), 'properties': { 'sound': { 'description': localize('accessibility.signals.lineHasError.sound', "Plays a sound when the active line has an error."), ...soundFeatureBase }, 'announcement': { - 'description': localize('accessibility.signals.lineHasError.announcement', "Indicates when the active line has an error."), + 'description': localize('accessibility.signals.lineHasError.announcement', "Announces when the active line has an error."), ...announcementFeatureBase, default: 'off' }, @@ -243,7 +243,7 @@ const configuration: IConfigurationNode = { }, 'accessibility.signals.lineHasFoldedArea': { ...signalFeatureBase, - 'description': localize('accessibility.signals.lineHasFoldedArea', "Indicates when the active line has a folded area that can be unfolded."), + 'description': localize('accessibility.signals.lineHasFoldedArea', "Plays a signal - sound (audio cue) and/or announcement (alert) - the active line has a folded area that can be unfolded."), 'properties': { 'sound': { 'description': localize('accessibility.signals.lineHasFoldedArea.sound', "Plays a sound when the active line has a folded area that can be unfolded."), @@ -251,21 +251,21 @@ const configuration: IConfigurationNode = { default: 'off' }, 'announcement': { - 'description': localize('accessibility.signals.lineHasFoldedArea.announcement', "Indicates when the active line has a folded area that can be unfolded."), + 'description': localize('accessibility.signals.lineHasFoldedArea.announcement', "Announces when the active line has a folded area that can be unfolded."), ...announcementFeatureBase }, } }, 'accessibility.signals.lineHasWarning': { ...signalFeatureBase, - 'description': localize('accessibility.signals.lineHasWarning', "Plays a signal when the active line has a warning."), + 'description': localize('accessibility.signals.lineHasWarning', "Plays a signal - sound (audio cue) and/or announcement (alert) - when the active line has a warning."), 'properties': { 'sound': { 'description': localize('accessibility.signals.lineHasWarning.sound', "Plays a sound when the active line has a warning."), ...soundFeatureBase }, 'announcement': { - 'description': localize('accessibility.signals.lineHasWarning.announcement', "Indicates when the active line has a warning."), + 'description': localize('accessibility.signals.lineHasWarning.announcement', "Announces when the active line has a warning."), ...announcementFeatureBase, default: 'off' }, @@ -273,14 +273,14 @@ const configuration: IConfigurationNode = { }, 'accessibility.signals.positionHasError': { ...signalFeatureBase, - 'description': localize('accessibility.signals.positionHasError', "Plays a signal when the active line has a warning."), + 'description': localize('accessibility.signals.positionHasError', "Plays a signal - sound (audio cue) and/or announcement (alert) - when the active line has a warning."), 'properties': { 'sound': { 'description': localize('accessibility.signals.positionHasError.sound', "Plays a sound when the active line has a warning."), ...soundFeatureBase }, 'announcement': { - 'description': localize('accessibility.signals.positionHasError.announcement', "Indicates when the active line has a warning."), + 'description': localize('accessibility.signals.positionHasError.announcement', "Announces when the active line has a warning."), ...announcementFeatureBase, default: 'on' }, @@ -288,14 +288,14 @@ const configuration: IConfigurationNode = { }, 'accessibility.signals.positionHasWarning': { ...signalFeatureBase, - 'description': localize('accessibility.signals.positionHasWarning', "Plays a signal when the active line has a warning."), + 'description': localize('accessibility.signals.positionHasWarning', "Plays a signal - sound (audio cue) and/or announcement (alert) - when the active line has a warning."), 'properties': { 'sound': { 'description': localize('accessibility.signals.positionHasWarning.sound', "Plays a sound when the active line has a warning."), ...soundFeatureBase }, 'announcement': { - 'description': localize('accessibility.signals.positionHasWarning.announcement', "Indicates when the active line has a warning."), + 'description': localize('accessibility.signals.positionHasWarning.announcement', "Announces when the active line has a warning."), ...announcementFeatureBase, default: 'on' }, @@ -303,105 +303,105 @@ const configuration: IConfigurationNode = { }, 'accessibility.signals.onDebugBreak': { ...signalFeatureBase, - 'description': localize('accessibility.signals.onDebugBreak', "Plays a signal when the debugger stopped on a breakpoint."), + 'description': localize('accessibility.signals.onDebugBreak', "Plays a signal - sound (audio cue) and/or announcement (alert) - when the debugger stopped on a breakpoint."), 'properties': { 'sound': { 'description': localize('accessibility.signals.onDebugBreak.sound', "Plays a sound when the debugger stopped on a breakpoint."), ...soundFeatureBase }, 'announcement': { - 'description': localize('accessibility.signals.onDebugBreak.announcement', "Indicates when the debugger stopped on a breakpoint."), + 'description': localize('accessibility.signals.onDebugBreak.announcement', "Announces when the debugger stopped on a breakpoint."), ...announcementFeatureBase }, } }, 'accessibility.signals.noInlayHints': { ...signalFeatureBase, - 'description': localize('accessibility.signals.noInlayHints', "Plays a signal when trying to read a line with inlay hints that has no inlay hints."), + 'description': localize('accessibility.signals.noInlayHints', "Plays a signal - sound (audio cue) and/or announcement (alert) - when trying to read a line with inlay hints that has no inlay hints."), 'properties': { 'sound': { 'description': localize('accessibility.signals.noInlayHints.sound', "Plays a sound when trying to read a line with inlay hints that has no inlay hints."), ...soundFeatureBase }, 'announcement': { - 'description': localize('accessibility.signals.noInlayHints.announcement', "Indicates when trying to read a line with inlay hints that has no inlay hints."), + 'description': localize('accessibility.signals.noInlayHints.announcement', "Announces when trying to read a line with inlay hints that has no inlay hints."), ...announcementFeatureBase }, } }, 'accessibility.signals.taskCompleted': { ...signalFeatureBase, - 'description': localize('accessibility.signals.taskCompleted', "Plays a signal when a task is completed."), + 'description': localize('accessibility.signals.taskCompleted', "Plays a signal - sound (audio cue) and/or announcement (alert) - when a task is completed."), 'properties': { 'sound': { 'description': localize('accessibility.signals.taskCompleted.sound', "Plays a sound when a task is completed."), ...soundFeatureBase }, 'announcement': { - 'description': localize('accessibility.signals.taskCompleted.announcement', "Indicates when a task is completed."), + 'description': localize('accessibility.signals.taskCompleted.announcement', "Announces when a task is completed."), ...announcementFeatureBase }, } }, 'accessibility.signals.taskFailed': { ...signalFeatureBase, - 'description': localize('accessibility.signals.taskFailed', "Plays a signal when a task fails (non-zero exit code)."), + 'description': localize('accessibility.signals.taskFailed', "Plays a signal - sound (audio cue) and/or announcement (alert) - when a task fails (non-zero exit code)."), 'properties': { 'sound': { 'description': localize('accessibility.signals.taskFailed.sound', "Plays a sound when a task fails (non-zero exit code)."), ...soundFeatureBase }, 'announcement': { - 'description': localize('accessibility.signals.taskFailed.announcement', "Indicates when a task fails (non-zero exit code)."), + 'description': localize('accessibility.signals.taskFailed.announcement', "Announces when a task fails (non-zero exit code)."), ...announcementFeatureBase }, } }, 'accessibility.signals.terminalCommandFailed': { ...signalFeatureBase, - 'description': localize('accessibility.signals.terminalCommandFailed', "Plays a signal when a terminal command fails (non-zero exit code) or when a command with such an exit code is navigated to in the accessible view."), + 'description': localize('accessibility.signals.terminalCommandFailed', "Plays a signal - sound (audio cue) and/or announcement (alert) - when a terminal command fails (non-zero exit code) or when a command with such an exit code is navigated to in the accessible view."), 'properties': { 'sound': { 'description': localize('accessibility.signals.terminalCommandFailed.sound', "Plays a sound when a terminal command fails (non-zero exit code) or when a command with such an exit code is navigated to in the accessible view."), ...soundFeatureBase }, 'announcement': { - 'description': localize('accessibility.signals.terminalCommandFailed.announcement', "Indicates when a terminal command fails (non-zero exit code) or when a command with such an exit code is navigated to in the accessible view."), + 'description': localize('accessibility.signals.terminalCommandFailed.announcement', "Announces when a terminal command fails (non-zero exit code) or when a command with such an exit code is navigated to in the accessible view."), ...announcementFeatureBase }, } }, 'accessibility.signals.terminalQuickFix': { ...signalFeatureBase, - 'description': localize('accessibility.signals.terminalQuickFix', "Plays a signal when terminal Quick Fixes are available."), + 'description': localize('accessibility.signals.terminalQuickFix', "Plays a signal - sound (audio cue) and/or announcement (alert) - when terminal Quick Fixes are available."), 'properties': { 'sound': { 'description': localize('accessibility.signals.terminalQuickFix.sound', "Plays a sound when terminal Quick Fixes are available."), ...soundFeatureBase }, 'announcement': { - 'description': localize('accessibility.signals.terminalQuickFix.announcement', "Indicates when terminal Quick Fixes are available."), + 'description': localize('accessibility.signals.terminalQuickFix.announcement', "Announces when terminal Quick Fixes are available."), ...announcementFeatureBase }, } }, 'accessibility.signals.terminalBell': { ...signalFeatureBase, - 'description': localize('accessibility.signals.terminalBell', "Plays a signal when the terminal bell is ringing."), + 'description': localize('accessibility.signals.terminalBell', "Plays a signal - sound (audio cue) and/or announcement (alert) - when the terminal bell is ringing."), 'properties': { 'sound': { 'description': localize('accessibility.signals.terminalBell.sound', "Plays a sound when the terminal bell is ringing."), ...soundFeatureBase }, 'announcement': { - 'description': localize('accessibility.signals.terminalBell.announcement', "Indicates when the terminal bell is ringing."), + 'description': localize('accessibility.signals.terminalBell.announcement', "Announces when the terminal bell is ringing."), ...announcementFeatureBase }, } }, 'accessibility.signals.diffLineInserted': { ...defaultNoAnnouncement, - 'description': localize('accessibility.signals.diffLineInserted', "Indicates when the focus moves to an inserted line in Accessible Diff Viewer mode or to the next/previous change."), + 'description': localize('accessibility.signals.diffLineInserted', "Plays a sound / audio cue when the focus moves to an inserted line in Accessible Diff Viewer mode or to the next/previous change."), 'properties': { 'sound': { 'description': localize('accessibility.signals.sound', "Plays a sound when the focus moves to an inserted line in Accessible Diff Viewer mode or to the next/previous change."), @@ -411,7 +411,7 @@ const configuration: IConfigurationNode = { }, 'accessibility.signals.diffLineModified': { ...defaultNoAnnouncement, - 'description': localize('accessibility.signals.diffLineModified', "Indicates when the focus moves to an modified line in Accessible Diff Viewer mode or to the next/previous change."), + 'description': localize('accessibility.signals.diffLineModified', "Plays a sound / audio cue when the focus moves to an modified line in Accessible Diff Viewer mode or to the next/previous change."), 'properties': { 'sound': { 'description': localize('accessibility.signals.diffLineModified.sound', "Plays a sound when the focus moves to a modified line in Accessible Diff Viewer mode or to the next/previous change."), @@ -421,7 +421,7 @@ const configuration: IConfigurationNode = { }, 'accessibility.signals.diffLineDeleted': { ...defaultNoAnnouncement, - 'description': localize('accessibility.signals.diffLineDeleted', "Indicates when the focus moves to an deleted line in Accessible Diff Viewer mode or to the next/previous change."), + 'description': localize('accessibility.signals.diffLineDeleted', "Plays a sound / audio cue when the focus moves to an deleted line in Accessible Diff Viewer mode or to the next/previous change."), 'properties': { 'sound': { 'description': localize('accessibility.signals.diffLineDeleted.sound', "Plays a sound when the focus moves to an deleted line in Accessible Diff Viewer mode or to the next/previous change."), @@ -431,49 +431,49 @@ const configuration: IConfigurationNode = { }, 'accessibility.signals.notebookCellCompleted': { ...signalFeatureBase, - 'description': localize('accessibility.signals.notebookCellCompleted', "Plays a signal when a notebook cell execution is successfully completed."), + 'description': localize('accessibility.signals.notebookCellCompleted', "Plays a signal - sound (audio cue) and/or announcement (alert) - when a notebook cell execution is successfully completed."), 'properties': { 'sound': { 'description': localize('accessibility.signals.notebookCellCompleted.sound', "Plays a sound when a notebook cell execution is successfully completed."), ...soundFeatureBase }, 'announcement': { - 'description': localize('accessibility.signals.notebookCellCompleted.announcement', "Indicates when a notebook cell execution is successfully completed."), + 'description': localize('accessibility.signals.notebookCellCompleted.announcement', "Announces when a notebook cell execution is successfully completed."), ...announcementFeatureBase }, } }, 'accessibility.signals.notebookCellFailed': { ...signalFeatureBase, - 'description': localize('accessibility.signals.notebookCellFailed', "Plays a signal when a notebook cell execution fails."), + 'description': localize('accessibility.signals.notebookCellFailed', "Plays a signal - sound (audio cue) and/or announcement (alert) - when a notebook cell execution fails."), 'properties': { 'sound': { 'description': localize('accessibility.signals.notebookCellFailed.sound', "Plays a sound when a notebook cell execution fails."), ...soundFeatureBase }, 'announcement': { - 'description': localize('accessibility.signals.notebookCellFailed.announcement', "Indicates when a notebook cell execution fails."), + 'description': localize('accessibility.signals.notebookCellFailed.announcement', "Announces when a notebook cell execution fails."), ...announcementFeatureBase }, } }, 'accessibility.signals.chatRequestSent': { ...signalFeatureBase, - 'description': localize('accessibility.signals.chatRequestSent', "Plays a signal when a chat request is made."), + 'description': localize('accessibility.signals.chatRequestSent', "Plays a signal - sound (audio cue) and/or announcement (alert) - when a chat request is made."), 'properties': { 'sound': { 'description': localize('accessibility.signals.chatRequestSent.sound', "Plays a sound when a chat request is made."), ...soundFeatureBase }, 'announcement': { - 'description': localize('accessibility.signals.chatRequestSent.announcement', "Indicates when a chat request is made."), + 'description': localize('accessibility.signals.chatRequestSent.announcement', "Announces when a chat request is made."), ...announcementFeatureBase }, } }, 'accessibility.signals.progress': { ...signalFeatureBase, - 'description': localize('accessibility.signals.progress', "Plays a signal on loop while progress is occurring."), + 'description': localize('accessibility.signals.progress', "Plays a signal - sound (audio cue) and/or announcement (alert) - on loop while progress is occurring."), 'properties': { 'sound': { 'description': localize('accessibility.signals.progress.sound', "Plays a sound on loop while progress is occurring."), @@ -487,7 +487,7 @@ const configuration: IConfigurationNode = { }, 'accessibility.signals.chatResponseReceived': { ...defaultNoAnnouncement, - 'description': localize('accessibility.signals.chatResponseReceived', "Indicates when the response has been received."), + 'description': localize('accessibility.signals.chatResponseReceived', "Plays a sound / audio cue when the response has been received."), 'properties': { 'sound': { 'description': localize('accessibility.signals.chatResponseReceived.sound', "Plays a sound on loop while the response has been received."), @@ -497,7 +497,7 @@ const configuration: IConfigurationNode = { }, 'accessibility.signals.voiceRecordingStarted': { ...defaultNoAnnouncement, - 'description': localize('accessibility.signals.voiceRecordingStarted', "Indicates when the voice recording has started."), + 'description': localize('accessibility.signals.voiceRecordingStarted', "Plays a sound / audio cue when the voice recording has started."), 'properties': { 'sound': { 'description': localize('accessibility.signals.voiceRecordingStarted.sound', "Plays a sound when the voice recording has started."), @@ -510,7 +510,7 @@ const configuration: IConfigurationNode = { }, 'accessibility.signals.voiceRecordingStopped': { ...defaultNoAnnouncement, - 'description': localize('accessibility.signals.voiceRecordingStopped', "Indicates when the voice recording has stopped."), + 'description': localize('accessibility.signals.voiceRecordingStopped', "Plays a sound / audio cue when the voice recording has stopped."), 'properties': { 'sound': { 'description': localize('accessibility.signals.voiceRecordingStopped.sound', "Plays a sound when the voice recording has stopped."), @@ -521,14 +521,14 @@ const configuration: IConfigurationNode = { }, 'accessibility.signals.clear': { ...signalFeatureBase, - 'description': localize('accessibility.signals.clear', "Plays a signal when a feature is cleared (for example, the terminal, Debug Console, or Output channel)."), + 'description': localize('accessibility.signals.clear', "Plays a signal - sound (audio cue) and/or announcement (alert) - when a feature is cleared (for example, the terminal, Debug Console, or Output channel)."), 'properties': { 'sound': { 'description': localize('accessibility.signals.clear.sound', "Plays a sound when a feature is cleared."), ...soundFeatureBase }, 'announcement': { - 'description': localize('accessibility.signals.clear.announcement', "Indicates when a feature is cleared."), + 'description': localize('accessibility.signals.clear.announcement', "Announces when a feature is cleared."), ...announcementFeatureBase }, }, @@ -537,7 +537,7 @@ const configuration: IConfigurationNode = { 'type': 'object', 'tags': ['accessibility'], additionalProperties: false, - 'markdownDescription': localize('accessibility.signals.save', "Plays a signal when a file is saved."), + 'markdownDescription': localize('accessibility.signals.save', "Plays a signal - sound (audio cue) and/or announcement (alert) - when a file is saved."), 'properties': { 'sound': { 'description': localize('accessibility.signals.save.sound', "Plays a sound when a file is saved."), @@ -551,7 +551,7 @@ const configuration: IConfigurationNode = { ], }, 'announcement': { - 'description': localize('accessibility.signals.save.announcement', "Indicates when a file is saved."), + 'description': localize('accessibility.signals.save.announcement', "Announces when a file is saved."), 'type': 'string', 'enum': ['userGesture', 'always', 'never'], 'default': 'never', @@ -571,7 +571,7 @@ const configuration: IConfigurationNode = { 'type': 'object', 'tags': ['accessibility'], additionalProperties: false, - 'markdownDescription': localize('accessibility.signals.format', "Plays a signal when a file or notebook is formatted."), + 'markdownDescription': localize('accessibility.signals.format', "Plays a signal - sound (audio cue) and/or announcement (alert) - when a file or notebook is formatted."), 'properties': { 'sound': { 'description': localize('accessibility.signals.format.sound', "Plays a sound when a file or notebook is formatted."), @@ -585,12 +585,12 @@ const configuration: IConfigurationNode = { ], }, 'announcement': { - 'description': localize('accessibility.signals.format.announcement', "Indicates when a file or notebook is formatted."), + 'description': localize('accessibility.signals.format.announcement', "Announces when a file or notebook is formatted."), 'type': 'string', 'enum': ['userGesture', 'always', 'never'], 'default': 'never', 'enumDescriptions': [ - localize('accessibility.signals.format.announcement.userGesture', "Announceswhen a user explicitly formats a file."), + localize('accessibility.signals.format.announcement.userGesture', "Announces when a user explicitly formats a file."), localize('accessibility.signals.format.announcement.always', "Announces whenever a file is formatted, including if it is set to format on save, type, or, paste, or run of a cell."), localize('accessibility.signals.format.announcement.never', "Never announces.") ], From 8ca394d456439b994025eca93cba3a2e52cac11b Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Fri, 26 Apr 2024 12:42:27 -0700 Subject: [PATCH 034/104] Don't consider 'progressMessage' to be part of the response content Fix #211165 --- src/vs/workbench/contrib/chat/common/chatModel.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/vs/workbench/contrib/chat/common/chatModel.ts b/src/vs/workbench/contrib/chat/common/chatModel.ts index b34f77970879b..9cf047a4b6a20 100644 --- a/src/vs/workbench/contrib/chat/common/chatModel.ts +++ b/src/vs/workbench/contrib/chat/common/chatModel.ts @@ -227,6 +227,8 @@ export class Response implements IResponse { return part.command.title; } else if (part.kind === 'textEditGroup') { return ''; + } else if (part.kind === 'progressMessage') { + return ''; } else { return part.content.value; } From 45cf75ebe4e893fc95de24d070957adc7a18d3e6 Mon Sep 17 00:00:00 2001 From: Logan Ramos Date: Fri, 26 Apr 2024 13:38:14 -0700 Subject: [PATCH 035/104] Update TAS client (#211484) --- package.json | 2 +- remote/package.json | 2 +- remote/web/package.json | 2 +- remote/web/yarn.lock | 8 ++++---- remote/yarn.lock | 8 ++++---- yarn.lock | 8 ++++---- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/package.json b/package.json index 4d9098974c0ba..ce9dd822377b3 100644 --- a/package.json +++ b/package.json @@ -98,7 +98,7 @@ "native-keymap": "^3.3.5", "native-watchdog": "^1.4.1", "node-pty": "1.1.0-beta11", - "tas-client-umd": "0.1.8", + "tas-client-umd": "0.2.0", "v8-inspect-profiler": "^0.1.1", "vscode-oniguruma": "1.7.0", "vscode-regexpp": "^3.1.0", diff --git a/remote/package.json b/remote/package.json index b65d496611349..c0397ce197f62 100644 --- a/remote/package.json +++ b/remote/package.json @@ -29,7 +29,7 @@ "minimist": "^1.2.6", "native-watchdog": "^1.4.1", "node-pty": "1.1.0-beta11", - "tas-client-umd": "0.1.8", + "tas-client-umd": "0.2.0", "vscode-oniguruma": "1.7.0", "vscode-regexpp": "^3.1.0", "vscode-textmate": "9.0.0", diff --git a/remote/web/package.json b/remote/web/package.json index 88588ecb87999..76375094a7dae 100644 --- a/remote/web/package.json +++ b/remote/web/package.json @@ -14,7 +14,7 @@ "@xterm/addon-webgl": "0.19.0-beta.17", "@xterm/xterm": "5.6.0-beta.17", "jschardet": "3.0.0", - "tas-client-umd": "0.1.8", + "tas-client-umd": "0.2.0", "vscode-oniguruma": "1.7.0", "vscode-textmate": "9.0.0" } diff --git a/remote/web/yarn.lock b/remote/web/yarn.lock index cb7ee772ee54f..81215235ac655 100644 --- a/remote/web/yarn.lock +++ b/remote/web/yarn.lock @@ -83,10 +83,10 @@ jschardet@3.0.0: resolved "https://registry.yarnpkg.com/jschardet/-/jschardet-3.0.0.tgz#898d2332e45ebabbdb6bf2feece9feea9a99e882" integrity sha512-lJH6tJ77V8Nzd5QWRkFYCLc13a3vADkh3r/Fi8HupZGWk2OVVDfnZP8V/VgQgZ+lzW0kG2UGb5hFgt3V3ndotQ== -tas-client-umd@0.1.8: - version "0.1.8" - resolved "https://registry.yarnpkg.com/tas-client-umd/-/tas-client-umd-0.1.8.tgz#38bd32d49545417a0ea67fb618e646298e1b67cc" - integrity sha512-0jAAujLmjjGXf9PzrNpjOrr/6CTpSOp8jX80NOHK5nlOTWWpwaZ16EOyrPdHnm2bVfPHvT0/RAD0xyiQHGQvCQ== +tas-client-umd@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/tas-client-umd/-/tas-client-umd-0.2.0.tgz#b71cc28f4c9b14f7b62f1ca4669886aa197e390c" + integrity sha512-oezN7mJVm5qZDVEby7OzxCLKUpUN5of0rY4dvOWaDF2JZBlGpd3BXceFN8B53qlTaIkVSzP65aAMT0Vc+/N25Q== vscode-oniguruma@1.7.0: version "1.7.0" diff --git a/remote/yarn.lock b/remote/yarn.lock index 683dabccbf3da..88d688b59549a 100644 --- a/remote/yarn.lock +++ b/remote/yarn.lock @@ -581,10 +581,10 @@ tar-stream@^2.1.4: inherits "^2.0.3" readable-stream "^3.1.1" -tas-client-umd@0.1.8: - version "0.1.8" - resolved "https://registry.yarnpkg.com/tas-client-umd/-/tas-client-umd-0.1.8.tgz#38bd32d49545417a0ea67fb618e646298e1b67cc" - integrity sha512-0jAAujLmjjGXf9PzrNpjOrr/6CTpSOp8jX80NOHK5nlOTWWpwaZ16EOyrPdHnm2bVfPHvT0/RAD0xyiQHGQvCQ== +tas-client-umd@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/tas-client-umd/-/tas-client-umd-0.2.0.tgz#b71cc28f4c9b14f7b62f1ca4669886aa197e390c" + integrity sha512-oezN7mJVm5qZDVEby7OzxCLKUpUN5of0rY4dvOWaDF2JZBlGpd3BXceFN8B53qlTaIkVSzP65aAMT0Vc+/N25Q== to-regex-range@^5.0.1: version "5.0.1" diff --git a/yarn.lock b/yarn.lock index 8b4c3ab95a869..a9ab6181dd6f2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9550,10 +9550,10 @@ tar@^6.1.11: mkdirp "^1.0.3" yallist "^4.0.0" -tas-client-umd@0.1.8: - version "0.1.8" - resolved "https://registry.yarnpkg.com/tas-client-umd/-/tas-client-umd-0.1.8.tgz#38bd32d49545417a0ea67fb618e646298e1b67cc" - integrity sha512-0jAAujLmjjGXf9PzrNpjOrr/6CTpSOp8jX80NOHK5nlOTWWpwaZ16EOyrPdHnm2bVfPHvT0/RAD0xyiQHGQvCQ== +tas-client-umd@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/tas-client-umd/-/tas-client-umd-0.2.0.tgz#b71cc28f4c9b14f7b62f1ca4669886aa197e390c" + integrity sha512-oezN7mJVm5qZDVEby7OzxCLKUpUN5of0rY4dvOWaDF2JZBlGpd3BXceFN8B53qlTaIkVSzP65aAMT0Vc+/N25Q== teex@^1.0.1: version "1.0.1" From 2d1620d01d351b298a076b8539980058e3b6ce47 Mon Sep 17 00:00:00 2001 From: Megan Rogge Date: Fri, 26 Apr 2024 14:09:49 -0700 Subject: [PATCH 036/104] add `accessibility.signalOptions` config, migrate settings to it (#211487) --- .../browser/accessibilityConfiguration.ts | 74 +++++++++++++++---- .../preferences/browser/settingsLayout.ts | 2 +- 2 files changed, 59 insertions(+), 17 deletions(-) diff --git a/src/vs/workbench/contrib/accessibility/browser/accessibilityConfiguration.ts b/src/vs/workbench/contrib/accessibility/browser/accessibilityConfiguration.ts index 8bd810cfcb4f3..ef8197fa3b01c 100644 --- a/src/vs/workbench/contrib/accessibility/browser/accessibilityConfiguration.ts +++ b/src/vs/workbench/contrib/accessibility/browser/accessibilityConfiguration.ts @@ -187,18 +187,27 @@ const configuration: IConfigurationNode = { type: 'boolean', default: true }, - 'accessibility.signals.sounds.volume': { - 'description': localize('accessibility.signals.sounds.volume', "The volume of the sounds in percent (0-100)."), - 'type': 'number', - 'minimum': 0, - 'maximum': 100, - 'default': 70, - tags: ['accessibility'] - }, - 'accessibility.signals.debouncePositionChanges': { - 'description': localize('accessibility.signals.debouncePositionChanges', "Whether or not position changes should be debounced"), - 'type': 'boolean', - 'default': false, + 'accessibility.signalOptions': { + type: 'object', + additionalProperties: false, + properties: { + 'volume': { + 'description': localize('accessibility.signalOptions.volume', "The volume of the sounds in percent (0-100)."), + 'type': 'number', + 'minimum': 0, + 'maximum': 100, + 'default': 70, + }, + 'debouncePositionChanges': { + 'description': localize('accessibility.signalOptions.debouncePositionChanges', "Whether or not position changes should be debounced"), + 'type': 'boolean', + 'default': false, + }, + }, + default: { + 'volume': 70, + 'debouncePositionChanges': false + }, tags: ['accessibility'] }, 'accessibility.signals.lineHasBreakpoint': { @@ -702,9 +711,10 @@ export class DynamicSpeechAccessibilityConfiguration extends Disposable implemen Registry.as(WorkbenchExtensions.ConfigurationMigration) .registerConfigurationMigrations([{ key: 'audioCues.volume', - migrateFn: (value, accessor) => { + migrateFn: (volume, accessor) => { + const debouncePositionChanges = getDebouncePositionChangesFromConfig(accessor); return [ - ['accessibility.signals.sounds.volume', { value }], + ['accessibility.signalOptions', { value: debouncePositionChanges !== undefined ? { volume, debouncePositionChanges } : { volume } }], ['audioCues.volume', { value: undefined }] ]; } @@ -713,14 +723,46 @@ Registry.as(WorkbenchExtensions.ConfigurationMi Registry.as(WorkbenchExtensions.ConfigurationMigration) .registerConfigurationMigrations([{ key: 'audioCues.debouncePositionChanges', - migrateFn: (value, accessor) => { + migrateFn: (debouncePositionChanges, accessor) => { + const volume = getVolumeFromConfig(accessor); return [ - ['accessibility.signals.debouncePositionChanges', { value }], + ['accessibility.signalOptions', { value: volume !== undefined ? { volume, debouncePositionChanges } : { debouncePositionChanges } }], ['audioCues.debouncePositionChanges', { value: undefined }] ]; } }]); +Registry.as(WorkbenchExtensions.ConfigurationMigration) + .registerConfigurationMigrations([{ + key: 'accessibility.signals.sounds.volume', + migrateFn: (volume, accessor) => { + const debouncePositionChanges = getDebouncePositionChangesFromConfig(accessor); + return [ + ['accessibility.signalOptions', { value: debouncePositionChanges !== undefined ? { volume, debouncePositionChanges } : { volume } }], + ['accessibility.signals.sounds.volume', { value: undefined }] + ]; + } + }]); + +Registry.as(WorkbenchExtensions.ConfigurationMigration) + .registerConfigurationMigrations([{ + key: 'accessibility.signals.debouncePositionChanges', + migrateFn: (debouncePositionChanges, accessor) => { + const volume = getVolumeFromConfig(accessor); + return [ + ['accessibility.signalOptions', { value: volume !== undefined ? { volume, debouncePositionChanges } : { debouncePositionChanges } }], + ['accessibility.signals.debouncePositionChanges', { value: undefined }] + ]; + } + }]); + +function getVolumeFromConfig(accessor: (key: string) => any): string | undefined { + return accessor('accessibility.signalOptions')?.volume || accessor('accessibility.signals.sounds.volume') || accessor('audioCues.volume'); +} + +function getDebouncePositionChangesFromConfig(accessor: (key: string) => any): number | undefined { + return accessor('accessibility.signalOptions')?.debouncePositionChanges || accessor('accessibility.signals.debouncePositionChanges') || accessor('audioCues.debouncePositionChanges'); +} Registry.as(WorkbenchExtensions.ConfigurationMigration) .registerConfigurationMigrations([{ diff --git a/src/vs/workbench/contrib/preferences/browser/settingsLayout.ts b/src/vs/workbench/contrib/preferences/browser/settingsLayout.ts index 6bee52d8257ab..72f128ed81f6c 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsLayout.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsLayout.ts @@ -149,7 +149,7 @@ export const tocData: ITOCEntry = { { id: 'features/accessibilitySignals', label: localize('accessibility.signals', 'Accessibility Signals'), - settings: ['accessibility.signals.*', 'audioCues.*'] + settings: ['accessibility.signals.*', 'accessibility.signalOptions.*'] }, { id: 'features/accessibility', From bf661a50b028984bda741532bd11c32942dcae63 Mon Sep 17 00:00:00 2001 From: Joyce Er Date: Fri, 26 Apr 2024 15:07:26 -0700 Subject: [PATCH 037/104] fix: clear chat completion disposables on next provider invocation (#211490) --- src/vs/workbench/api/common/extHostChatAgents2.ts | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/api/common/extHostChatAgents2.ts b/src/vs/workbench/api/common/extHostChatAgents2.ts index abc3e0e4b7dca..b53f624362e14 100644 --- a/src/vs/workbench/api/common/extHostChatAgents2.ts +++ b/src/vs/workbench/api/common/extHostChatAgents2.ts @@ -206,7 +206,7 @@ export class ExtHostChatAgents2 extends Disposable implements ExtHostChatAgentsS private readonly _proxy: MainThreadChatAgentsShape2; private readonly _sessionDisposables: DisposableMap = this._register(new DisposableMap()); - private readonly _completionDisposables = this._register(new DisposableStore()); + private readonly _completionDisposables: DisposableMap = this._register(new DisposableMap()); constructor( mainContext: IMainContext, @@ -374,9 +374,18 @@ export class ExtHostChatAgents2 extends Disposable implements ExtHostChatAgentsS return []; } + let disposables = this._completionDisposables.get(handle); + if (disposables) { + // Clear any disposables from the last invocation of this completion provider + disposables.clear(); + } else { + disposables = new DisposableStore(); + this._completionDisposables.set(handle, disposables); + } + const items = await agent.invokeCompletionProvider(query, token); - return items.map((i) => typeConvert.ChatAgentCompletionItem.from(i, this.commands.converter, this._completionDisposables)); + return items.map((i) => typeConvert.ChatAgentCompletionItem.from(i, this.commands.converter, disposables)); } async $provideWelcomeMessage(handle: number, location: ChatAgentLocation, token: CancellationToken): Promise<(string | IMarkdownString)[] | undefined> { From 233775583c00f6dec15c61985e56ff429550e500 Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Fri, 26 Apr 2024 15:23:02 -0700 Subject: [PATCH 038/104] cli: warn when cli options are not applied (#211492) Fixes #211378 --- cli/src/commands/tunnels.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/cli/src/commands/tunnels.rs b/cli/src/commands/tunnels.rs index 98a2a2e3a3a65..f06cd9a1e2a2e 100644 --- a/cli/src/commands/tunnels.rs +++ b/cli/src/commands/tunnels.rs @@ -556,6 +556,16 @@ async fn serve_with_csa( match acquire_singleton(&paths.tunnel_lockfile()).await { Ok(SingletonConnection::Client(stream)) => { debug!(log, "starting as client to singleton"); + if gateway_args.name.is_none() + || !gateway_args.install_extension.is_empty() + || gateway_args.tunnel.tunnel_id.is_some() + { + warning!( + log, + "Command-line options will not be applied until the existing tunnel exits." + ); + } + let should_exit = start_singleton_client(SingletonClientArgs { log: log.clone(), shutdown: shutdown.clone(), From 1357fca0f785b29c71a86fc3dddfe0e5da47eba1 Mon Sep 17 00:00:00 2001 From: Tyler James Leonhardt Date: Fri, 26 Apr 2024 16:06:58 -0700 Subject: [PATCH 039/104] Add cancellable promise to Microsoft auth flows (#211495) Fixes #211406 --- .../microsoft-authentication/src/AADHelper.ts | 48 +++++++++---------- .../src/common/async.ts | 35 +++++++++++++- .../api/common/extHostAuthentication.ts | 12 ++--- .../authenticationExtensionsService.ts | 15 ++++-- 4 files changed, 73 insertions(+), 37 deletions(-) diff --git a/extensions/microsoft-authentication/src/AADHelper.ts b/extensions/microsoft-authentication/src/AADHelper.ts index 0417defe534d8..df36686dc9a3d 100644 --- a/extensions/microsoft-authentication/src/AADHelper.ts +++ b/extensions/microsoft-authentication/src/AADHelper.ts @@ -6,7 +6,7 @@ import * as vscode from 'vscode'; import * as path from 'path'; import { isSupportedEnvironment } from './common/uri'; -import { IntervalTimer, SequencerByKey } from './common/async'; +import { IntervalTimer, raceCancellationAndTimeoutError, SequencerByKey } from './common/async'; import { generateCodeChallenge, generateCodeVerifier, randomUUID } from './cryptoUtils'; import { BetterTokenStorage, IDidChangeInOtherWindowEvent } from './betterSecretStorage'; import { LoopbackAuthServer } from './node/authServer'; @@ -314,25 +314,27 @@ export class AzureActiveDirectoryService { throw new Error('Sign in to non-public clouds is not supported on the web.'); } - if (runsRemote || runsServerless) { - return this.createSessionWithoutLocalServer(scopeData); - } + return await vscode.window.withProgress({ location: vscode.ProgressLocation.Notification, title: vscode.l10n.t('Signing in to your account...'), cancellable: true }, async (_progress, token) => { + if (runsRemote || runsServerless) { + return await this.createSessionWithoutLocalServer(scopeData, token); + } - try { - return await this.createSessionWithLocalServer(scopeData); - } catch (e) { - this._logger.error(`[${scopeData.scopeStr}] Error creating session: ${e}`); + try { + return await this.createSessionWithLocalServer(scopeData, token); + } catch (e) { + this._logger.error(`[${scopeData.scopeStr}] Error creating session: ${e}`); - // If the error was about starting the server, try directly hitting the login endpoint instead - if (e.message === 'Error listening to server' || e.message === 'Closed' || e.message === 'Timeout waiting for port') { - return this.createSessionWithoutLocalServer(scopeData); - } + // If the error was about starting the server, try directly hitting the login endpoint instead + if (e.message === 'Error listening to server' || e.message === 'Closed' || e.message === 'Timeout waiting for port') { + return this.createSessionWithoutLocalServer(scopeData, token); + } - throw e; - } + throw e; + } + }); } - private async createSessionWithLocalServer(scopeData: IScopeData) { + private async createSessionWithLocalServer(scopeData: IScopeData, token: vscode.CancellationToken): Promise { this._logger.trace(`[${scopeData.scopeStr}] Starting login flow with local server`); const codeVerifier = generateCodeVerifier(); const codeChallenge = await generateCodeChallenge(codeVerifier); @@ -353,7 +355,7 @@ export class AzureActiveDirectoryService { let codeToExchange; try { vscode.env.openExternal(vscode.Uri.parse(`http://127.0.0.1:${server.port}/signin?nonce=${encodeURIComponent(server.nonce)}`)); - const { code } = await server.waitForOAuthResponse(); + const { code } = await raceCancellationAndTimeoutError(server.waitForOAuthResponse(), token, 1000 * 60 * 5); // 5 minutes codeToExchange = code; } finally { setTimeout(() => { @@ -368,7 +370,7 @@ export class AzureActiveDirectoryService { return session; } - private async createSessionWithoutLocalServer(scopeData: IScopeData): Promise { + private async createSessionWithoutLocalServer(scopeData: IScopeData, token: vscode.CancellationToken): Promise { this._logger.trace(`[${scopeData.scopeStr}] Starting login flow without local server`); let callbackUri = await vscode.env.asExternalUri(vscode.Uri.parse(`${vscode.env.uriScheme}://vscode.microsoft-authentication`)); const nonce = generateCodeVerifier(); @@ -395,14 +397,6 @@ export class AzureActiveDirectoryService { const uri = vscode.Uri.parse(signInUrl.toString()); vscode.env.openExternal(uri); - let inputBox: vscode.InputBox | undefined; - const timeoutPromise = new Promise((_: (value: vscode.AuthenticationSession) => void, reject) => { - const wait = setTimeout(() => { - clearTimeout(wait); - inputBox?.dispose(); - reject('Login timed out.'); - }, 1000 * 60 * 5); - }); const existingNonces = this._pendingNonces.get(scopeData.scopeStr) || []; this._pendingNonces.set(scopeData.scopeStr, [...existingNonces, nonce]); @@ -410,6 +404,7 @@ export class AzureActiveDirectoryService { // Register a single listener for the URI callback, in case the user starts the login process multiple times // before completing it. let existingPromise = this._codeExchangePromises.get(scopeData.scopeStr); + let inputBox: vscode.InputBox | undefined; if (!existingPromise) { if (isSupportedEnvironment(callbackUri)) { existingPromise = this.handleCodeResponse(scopeData); @@ -422,11 +417,12 @@ export class AzureActiveDirectoryService { this._codeVerfifiers.set(nonce, codeVerifier); - return Promise.race([existingPromise, timeoutPromise]) + return await raceCancellationAndTimeoutError(existingPromise, token, 1000 * 60 * 5) // 5 minutes .finally(() => { this._pendingNonces.delete(scopeData.scopeStr); this._codeExchangePromises.delete(scopeData.scopeStr); this._codeVerfifiers.delete(nonce); + inputBox?.dispose(); }); } diff --git a/extensions/microsoft-authentication/src/common/async.ts b/extensions/microsoft-authentication/src/common/async.ts index 527b5bbb39942..641faaff0ddaa 100644 --- a/extensions/microsoft-authentication/src/common/async.ts +++ b/extensions/microsoft-authentication/src/common/async.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Disposable } from 'vscode'; +import { CancellationError, CancellationToken, Disposable } from 'vscode'; export class SequencerByKey { @@ -47,3 +47,36 @@ export class IntervalTimer extends Disposable { }, interval); } } + +/** + * Returns a promise that rejects with an {@CancellationError} as soon as the passed token is cancelled. + * @see {@link raceCancellation} + */ +export function raceCancellationError(promise: Promise, token: CancellationToken): Promise { + return new Promise((resolve, reject) => { + const ref = token.onCancellationRequested(() => { + ref.dispose(); + reject(new CancellationError()); + }); + promise.then(resolve, reject).finally(() => ref.dispose()); + }); +} + +export class TimeoutError extends Error { + constructor() { + super('Timed out'); + } +} + +export function raceTimeoutError(promise: Promise, timeout: number): Promise { + return new Promise((resolve, reject) => { + const ref = setTimeout(() => { + reject(new CancellationError()); + }, timeout); + promise.then(resolve, reject).finally(() => clearTimeout(ref)); + }); +} + +export function raceCancellationAndTimeoutError(promise: Promise, token: CancellationToken, timeout: number): Promise { + return raceCancellationError(raceTimeoutError(promise, timeout), token); +} diff --git a/src/vs/workbench/api/common/extHostAuthentication.ts b/src/vs/workbench/api/common/extHostAuthentication.ts index 1c562edf76a19..16b1d4a405ba1 100644 --- a/src/vs/workbench/api/common/extHostAuthentication.ts +++ b/src/vs/workbench/api/common/extHostAuthentication.ts @@ -89,28 +89,28 @@ export class ExtHostAuthentication implements ExtHostAuthenticationShape { }); } - $createSession(providerId: string, scopes: string[], options: vscode.AuthenticationProviderCreateSessionOptions): Promise { + async $createSession(providerId: string, scopes: string[], options: vscode.AuthenticationProviderCreateSessionOptions): Promise { const providerData = this._authenticationProviders.get(providerId); if (providerData) { - return Promise.resolve(providerData.provider.createSession(scopes, options)); + return await providerData.provider.createSession(scopes, options); } throw new Error(`Unable to find authentication provider with handle: ${providerId}`); } - $removeSession(providerId: string, sessionId: string): Promise { + async $removeSession(providerId: string, sessionId: string): Promise { const providerData = this._authenticationProviders.get(providerId); if (providerData) { - return Promise.resolve(providerData.provider.removeSession(sessionId)); + return await providerData.provider.removeSession(sessionId); } throw new Error(`Unable to find authentication provider with handle: ${providerId}`); } - $getSessions(providerId: string, scopes?: string[]): Promise> { + async $getSessions(providerId: string, scopes?: string[]): Promise> { const providerData = this._authenticationProviders.get(providerId); if (providerData) { - return Promise.resolve(providerData.provider.getSessions(scopes)); + return await providerData.provider.getSessions(scopes); } throw new Error(`Unable to find authentication provider with handle: ${providerId}`); diff --git a/src/vs/workbench/services/authentication/browser/authenticationExtensionsService.ts b/src/vs/workbench/services/authentication/browser/authenticationExtensionsService.ts index 3ffce7c44d9ce..1cdb2d5a5aeeb 100644 --- a/src/vs/workbench/services/authentication/browser/authenticationExtensionsService.ts +++ b/src/vs/workbench/services/authentication/browser/authenticationExtensionsService.ts @@ -246,23 +246,30 @@ export class AuthenticationExtensionsService extends Disposable implements IAuth quickPick.placeholder = nls.localize('getSessionPlateholder', "Select an account for '{0}' to use or Esc to cancel", extensionName); quickPick.onDidAccept(async _ => { - const session = quickPick.selectedItems[0].session ?? await this._authenticationService.createSession(providerId, scopes); + quickPick.dispose(); + let session = quickPick.selectedItems[0].session; + if (!session) { + try { + session = await this._authenticationService.createSession(providerId, scopes); + } catch (e) { + reject(e); + return; + } + } const accountName = session.account.label; this._authenticationAccessService.updateAllowedExtensions(providerId, accountName, [{ id: extensionId, name: extensionName, allowed: true }]); this.updateSessionPreference(providerId, extensionId, session); this.removeAccessRequest(providerId, extensionId); - quickPick.dispose(); resolve(session); }); quickPick.onDidHide(_ => { + quickPick.dispose(); if (!quickPick.selectedItems[0]) { reject('User did not consent to account access'); } - - quickPick.dispose(); }); quickPick.show(); From 60bd03a02e2cd54b80b9a9a07429758eeffde06b Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Fri, 26 Apr 2024 16:38:38 -0700 Subject: [PATCH 040/104] cli: fix tunnels not working on Windows (#211498) I made a change this past iteration to use `CREATE_BREAKAWAY_FROM_JOB` in order to allow the code-server process to outlive SSH connections run from the exec server. However, it appears that this _can_ break things if it's run from a job that doesn't have the JOB_OBJECT_LIMIT_BREAKAWAY_OK flag set. I'm not a winapi expert, so this is a simple though perhaps inefficient change to probe whether we can do this via an echo command before starting the server. --- cli/src/tunnels/code_server.rs | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/cli/src/tunnels/code_server.rs b/cli/src/tunnels/code_server.rs index 16cc3325a4a8e..c9821446049d8 100644 --- a/cli/src/tunnels/code_server.rs +++ b/cli/src/tunnels/code_server.rs @@ -479,7 +479,7 @@ impl<'a> ServerBuilder<'a> { .arg("--enable-remote-auto-shutdown") .arg(format!("--port={}", port)); - let child = self.spawn_server_process(cmd)?; + let child = self.spawn_server_process(cmd).await?; let log_file = self.get_logfile()?; let plog = self.logger.prefixed(&log::new_code_server_prefix()); @@ -553,7 +553,7 @@ impl<'a> ServerBuilder<'a> { .arg("--enable-remote-auto-shutdown") .arg(format!("--socket-path={}", socket.display())); - let child = self.spawn_server_process(cmd)?; + let child = self.spawn_server_process(cmd).await?; let log_file = self.get_logfile()?; let plog = self.logger.prefixed(&log::new_code_server_prefix()); @@ -594,13 +594,13 @@ impl<'a> ServerBuilder<'a> { let mut cmd = self.get_base_command(); cmd.args(args); - let child = self.spawn_server_process(cmd)?; + let child = self.spawn_server_process(cmd).await?; let plog = self.logger.prefixed(&log::new_code_server_prefix()); Ok(monitor_server::(child, None, plog, true)) } - fn spawn_server_process(&self, mut cmd: Command) -> Result { + async fn spawn_server_process(&self, mut cmd: Command) -> Result { info!(self.logger, "Starting server..."); debug!(self.logger, "Starting server with command... {:?}", cmd); @@ -615,7 +615,10 @@ impl<'a> ServerBuilder<'a> { let cmd = cmd.creation_flags( winapi::um::winbase::CREATE_NO_WINDOW | winapi::um::winbase::CREATE_NEW_PROCESS_GROUP - | winapi::um::winbase::CREATE_BREAKAWAY_FROM_JOB, + | get_should_use_breakaway_from_job() + .await + .then_some(winapi::um::winbase::CREATE_BREAKAWAY_FROM_JOB) + .unwrap_or_default(), ); let child = cmd @@ -874,3 +877,13 @@ pub async fn download_cli_into_cache( } } } + +#[cfg(target_os = "windows")] +async fn get_should_use_breakaway_from_job() -> bool { + let mut cmd = Command::new("cmd"); + cmd.creation_flags( + winapi::um::winbase::CREATE_NO_WINDOW | winapi::um::winbase::CREATE_BREAKAWAY_FROM_JOB, + ); + + cmd.args(["/C", "echo ok"]).output().await.is_ok() +} From 220eb8e2a5b62834c963484eefcca0c0a9d80141 Mon Sep 17 00:00:00 2001 From: Andrea Mah <31675041+andreamah@users.noreply.github.com> Date: Fri, 26 Apr 2024 16:52:08 -0700 Subject: [PATCH 041/104] Remove Search 'Expand Recursively' for FileMatch items in search view (#211496) Fixes #211474 --- .../workbench/contrib/search/browser/searchActionsFind.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/contrib/search/browser/searchActionsFind.ts b/src/vs/workbench/contrib/search/browser/searchActionsFind.ts index 2051b1d13741b..bd4676d881c63 100644 --- a/src/vs/workbench/contrib/search/browser/searchActionsFind.ts +++ b/src/vs/workbench/contrib/search/browser/searchActionsFind.ts @@ -88,7 +88,7 @@ registerAction2(class ExpandSelectedTreeCommandAction extends Action2 { menu: [{ id: MenuId.SearchContext, when: ContextKeyExpr.and( - ContextKeyExpr.or(Constants.SearchContext.FileFocusKey, Constants.SearchContext.FolderFocusKey), + Constants.SearchContext.FolderFocusKey, Constants.SearchContext.HasSearchResults ), group: 'search', @@ -97,8 +97,8 @@ registerAction2(class ExpandSelectedTreeCommandAction extends Action2 { }); } - override async run(accessor: any): Promise { - await expandSelectSubtree(accessor); + override run(accessor: any) { + expandSelectSubtree(accessor); } }); From 7a91d684b364dc6635b73916099dde0aa676593a Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Fri, 26 Apr 2024 17:09:56 -0700 Subject: [PATCH 042/104] Don't register on already disposed objects --- src/vs/workbench/contrib/terminal/browser/terminalInstance.ts | 3 +++ .../stickyScroll/browser/terminalStickyScrollOverlay.ts | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts index 97f735e675c7b..a53fb826303cb 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts @@ -1452,6 +1452,9 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { } } }); + if (this.isDisposed) { + return; + } if (this.xterm?.shellIntegration) { this.capabilities.add(this.xterm.shellIntegration.capabilities); } diff --git a/src/vs/workbench/contrib/terminalContrib/stickyScroll/browser/terminalStickyScrollOverlay.ts b/src/vs/workbench/contrib/terminalContrib/stickyScroll/browser/terminalStickyScrollOverlay.ts index eac420466bbf8..82bf0918221f0 100644 --- a/src/vs/workbench/contrib/terminalContrib/stickyScroll/browser/terminalStickyScrollOverlay.ts +++ b/src/vs/workbench/contrib/terminalContrib/stickyScroll/browser/terminalStickyScrollOverlay.ts @@ -119,6 +119,9 @@ export class TerminalStickyScrollOverlay extends Disposable { })); this._getSerializeAddonConstructor().then(SerializeAddon => { + if (this._store.isDisposed) { + return; + } this._serializeAddon = this._register(new SerializeAddon()); this._xterm.raw.loadAddon(this._serializeAddon); // Trigger a render as the serialize addon is required to render From d308e233405bf8d6e3c8e1135d1f1a8e0252a65e Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Fri, 26 Apr 2024 17:18:41 -0700 Subject: [PATCH 043/104] Disable suggest unless pwsh --- src/vs/workbench/contrib/terminal/common/terminal.ts | 1 + .../suggest/browser/terminal.suggest.contribution.ts | 6 +++++- .../suggest/browser/terminalSuggestAddon.ts | 11 ++++++++--- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/common/terminal.ts b/src/vs/workbench/contrib/terminal/common/terminal.ts index a2c8e2a804ed1..71de8f0cceb65 100644 --- a/src/vs/workbench/contrib/terminal/common/terminal.ts +++ b/src/vs/workbench/contrib/terminal/common/terminal.ts @@ -202,6 +202,7 @@ export interface ITerminalConfiguration { shellIntegration?: { enabled: boolean; decorationsEnabled: boolean; + suggestEnabled: boolean; }; enableImages: boolean; smoothScrolling: boolean; diff --git a/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminal.suggest.contribution.ts b/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminal.suggest.contribution.ts index 512373ba4a296..73821b548f066 100644 --- a/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminal.suggest.contribution.ts +++ b/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminal.suggest.contribution.ts @@ -19,7 +19,7 @@ import { localize2 } from 'vs/nls'; import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { KeyCode } from 'vs/base/common/keyCodes'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { TerminalSettingId } from 'vs/platform/terminal/common/terminal'; +import { PosixShellType, TerminalSettingId, WindowsShellType } from 'vs/platform/terminal/common/terminal'; class TerminalSuggestContribution extends DisposableStore implements ITerminalContribution { static readonly ID = 'terminal.suggest'; @@ -48,6 +48,10 @@ class TerminalSuggestContribution extends DisposableStore implements ITerminalCo } xtermOpen(xterm: IXtermTerminal & { raw: RawXtermTerminal }): void { + // While pwsh is the only supported shell, disable completely when not pwsh + if (this._instance.shellType !== 'pwsh') { + return; + } this._loadSuggestAddon(xterm.raw); this.add(this._contextKeyService.onDidChangeContext(e => { if (e.affectsSome(this._terminalSuggestWidgetContextKeys)) { diff --git a/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon.ts b/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon.ts index ecf1ea09c0e3e..b8af40c5e618a 100644 --- a/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon.ts +++ b/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon.ts @@ -16,7 +16,7 @@ import { IContextKey } from 'vs/platform/contextkey/common/contextkey'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { activeContrastBorder } from 'vs/platform/theme/common/colorRegistry'; -import { ISuggestController } from 'vs/workbench/contrib/terminal/browser/terminal'; +import { ISuggestController, ITerminalConfigurationService } from 'vs/workbench/contrib/terminal/browser/terminal'; import { TerminalStorageKeys } from 'vs/workbench/contrib/terminal/common/terminalStorageKeys'; import type { ITerminalAddon, Terminal } from '@xterm/xterm'; @@ -99,7 +99,8 @@ export class SuggestAddon extends Disposable implements ITerminalAddon, ISuggest constructor( private readonly _capabilities: ITerminalCapabilityStore, private readonly _terminalSuggestWidgetVisibleContextKey: IContextKey, - @IInstantiationService private readonly _instantiationService: IInstantiationService + @IInstantiationService private readonly _instantiationService: IInstantiationService, + @ITerminalConfigurationService private readonly _terminalConfigurationService: ITerminalConfigurationService ) { super(); @@ -139,10 +140,15 @@ export class SuggestAddon extends Disposable implements ITerminalAddon, ISuggest private _requestCompletions(): void { // TODO: Debounce? Prevent this flooding the channel + // if (this._terminal. this._onAcceptedCompletion.fire('\x1b[24~e'); } private _sync(promptInputState: IPromptInputModelState): void { + if (!this._terminalConfigurationService.config.shellIntegration?.suggestEnabled) { + return; + } + if (!this._terminalSuggestWidgetVisibleContextKey.get()) { // If input has been added if (!this._mostRecentPromptInputState || promptInputState.cursorIndex > this._mostRecentPromptInputState.cursorIndex) { @@ -162,7 +168,6 @@ export class SuggestAddon extends Disposable implements ITerminalAddon, ISuggest } this._mostRecentPromptInputState = promptInputState; - // this._onAcceptedCompletion.fire('\x1b[24~e'); if (!this._promptInputModel || !this._terminal || !this._suggestWidget || !this._initialPromptInputState) { return; } From 2f6030c7046040748d1d5080cfa6508b61a673bf Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Fri, 26 Apr 2024 17:19:13 -0700 Subject: [PATCH 044/104] Remove unused imports --- .../suggest/browser/terminal.suggest.contribution.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminal.suggest.contribution.ts b/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminal.suggest.contribution.ts index 73821b548f066..ba8f14ee8f9e8 100644 --- a/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminal.suggest.contribution.ts +++ b/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminal.suggest.contribution.ts @@ -19,7 +19,7 @@ import { localize2 } from 'vs/nls'; import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { KeyCode } from 'vs/base/common/keyCodes'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { PosixShellType, TerminalSettingId, WindowsShellType } from 'vs/platform/terminal/common/terminal'; +import { TerminalSettingId } from 'vs/platform/terminal/common/terminal'; class TerminalSuggestContribution extends DisposableStore implements ITerminalContribution { static readonly ID = 'terminal.suggest'; From 0f2b53566208483a0309c349daeff957c868ba11 Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Sat, 27 Apr 2024 06:54:06 -0700 Subject: [PATCH 045/104] cli: automatically remove servers that fail to start (#211500) Fixes /~https://github.com/microsoft/vscode-remote-release/issues/9823 --- cli/src/tunnels/code_server.rs | 55 +++++++++++++------------------ cli/src/tunnels/control_server.rs | 25 ++++++++++++-- cli/src/util/errors.rs | 4 +++ 3 files changed, 49 insertions(+), 35 deletions(-) diff --git a/cli/src/tunnels/code_server.rs b/cli/src/tunnels/code_server.rs index c9821446049d8..0579f8ef0dcfe 100644 --- a/cli/src/tunnels/code_server.rs +++ b/cli/src/tunnels/code_server.rs @@ -394,6 +394,16 @@ impl<'a> ServerBuilder<'a> { } } + /// Removes a cached server. + pub async fn evict(&self) -> Result<(), WrappedError> { + let name = get_server_folder_name( + self.server_params.release.quality, + &self.server_params.release.commit, + ); + + self.launcher_paths.server_cache.delete(&name) + } + /// Ensures the server is set up in the configured directory. pub async fn setup(&self) -> Result<(), AnyError> { debug!( @@ -487,16 +497,16 @@ impl<'a> ServerBuilder<'a> { monitor_server::(child, Some(log_file), plog, false); let port = match timeout(Duration::from_secs(8), listen_rx).await { - Err(e) => { + Err(_) => { origin.kill().await; - Err(wrap(e, "timed out looking for port")) + return Err(CodeError::ServerOriginTimeout.into()); } - Ok(Err(e)) => { + Ok(Err(s)) => { origin.kill().await; - Err(wrap(e, "server exited without writing port")) + return Err(CodeError::ServerUnexpectedExit(format!("{}", s)).into()); } - Ok(Ok(p)) => Ok(p), - }?; + Ok(Ok(p)) => p, + }; info!(self.logger, "Server started"); @@ -561,16 +571,16 @@ impl<'a> ServerBuilder<'a> { monitor_server::(child, Some(log_file), plog, false); let socket = match timeout(Duration::from_secs(30), listen_rx).await { - Err(e) => { + Err(_) => { origin.kill().await; - Err(wrap(e, "timed out looking for socket")) + return Err(CodeError::ServerOriginTimeout.into()); } - Ok(Err(e)) => { + Ok(Err(s)) => { origin.kill().await; - Err(wrap(e, "server exited without writing socket")) + return Err(CodeError::ServerUnexpectedExit(format!("{}", s)).into()); } - Ok(Ok(socket)) => Ok(socket), - }?; + Ok(Ok(socket)) => socket, + }; info!(self.logger, "Server started"); @@ -581,25 +591,6 @@ impl<'a> ServerBuilder<'a> { }) } - /// Starts with a given opaque set of args. Does not set up any port or - /// socket, but does return one if present, in the form of a channel. - pub async fn start_opaque_with_args( - &self, - args: &[String], - ) -> Result<(CodeServerOrigin, Receiver), AnyError> - where - M: ServerOutputMatcher, - R: 'static + Send + std::fmt::Debug, - { - let mut cmd = self.get_base_command(); - cmd.args(args); - - let child = self.spawn_server_process(cmd).await?; - let plog = self.logger.prefixed(&log::new_code_server_prefix()); - - Ok(monitor_server::(child, None, plog, true)) - } - async fn spawn_server_process(&self, mut cmd: Command) -> Result { info!(self.logger, "Starting server..."); @@ -625,7 +616,7 @@ impl<'a> ServerBuilder<'a> { .stderr(std::process::Stdio::piped()) .stdout(std::process::Stdio::piped()) .spawn() - .map_err(|e| wrap(e, "error spawning server"))?; + .map_err(|e| CodeError::ServerUnexpectedExit(format!("{}", e)))?; self.server_paths .write_pid(child.id().expect("expected server to have pid"))?; diff --git a/cli/src/tunnels/control_server.rs b/cli/src/tunnels/control_server.rs index ec09e4512a06e..f42984cfac150 100644 --- a/cli/src/tunnels/control_server.rs +++ b/cli/src/tunnels/control_server.rs @@ -760,17 +760,18 @@ async fn handle_serve( macro_rules! do_setup { ($sb:expr) => { match $sb.get_running().await? { - Some(AnyCodeServer::Socket(s)) => s, + Some(AnyCodeServer::Socket(s)) => ($sb, Ok(s)), Some(_) => return Err(AnyError::from(MismatchedLaunchModeError())), None => { $sb.setup().await?; - $sb.listen_on_default_socket().await? + let r = $sb.listen_on_default_socket().await; + ($sb, r) } } }; } - let server = if params.use_local_download { + let (sb, server) = if params.use_local_download { let sb = ServerBuilder::new( &install_log, &resolved, @@ -784,6 +785,24 @@ async fn handle_serve( do_setup!(sb) }; + let server = match server { + Ok(s) => s, + Err(e) => { + // we don't loop to avoid doing so infinitely: allow the client to reconnect in this case. + if let AnyError::CodeError(CodeError::ServerUnexpectedExit(ref e)) = e { + warning!( + c.log, + "({}), removing server due to possible corruptions", + e + ); + if let Err(e) = sb.evict().await { + warning!(c.log, "Failed to evict server: {}", e); + } + } + return Err(e); + } + }; + server_ref.replace(server.clone()); server } diff --git a/cli/src/util/errors.rs b/cli/src/util/errors.rs index fc706199aabe8..7d28ce9f741ba 100644 --- a/cli/src/util/errors.rs +++ b/cli/src/util/errors.rs @@ -516,6 +516,10 @@ pub enum CodeError { CouldNotCreateConnectionTokenFile(std::io::Error), #[error("A tunnel with the name {0} exists and is in-use. Please pick a different name or stop the existing tunnel.")] TunnelActiveAndInUse(String), + #[error("Timed out looking for port/socket")] + ServerOriginTimeout, + #[error("Server exited without writing port/socket: {0}")] + ServerUnexpectedExit(String), } makeAnyError!( From e46f4aeb5f585d4e169960d91d7d7307166d1314 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Sat, 27 Apr 2024 07:45:36 -0700 Subject: [PATCH 046/104] Don't disable based on shell type --- .../suggest/browser/terminal.suggest.contribution.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminal.suggest.contribution.ts b/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminal.suggest.contribution.ts index ba8f14ee8f9e8..512373ba4a296 100644 --- a/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminal.suggest.contribution.ts +++ b/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminal.suggest.contribution.ts @@ -48,10 +48,6 @@ class TerminalSuggestContribution extends DisposableStore implements ITerminalCo } xtermOpen(xterm: IXtermTerminal & { raw: RawXtermTerminal }): void { - // While pwsh is the only supported shell, disable completely when not pwsh - if (this._instance.shellType !== 'pwsh') { - return; - } this._loadSuggestAddon(xterm.raw); this.add(this._contextKeyService.onDidChangeContext(e => { if (e.affectsSome(this._terminalSuggestWidgetContextKeys)) { From de91037b799a300a3ecce94df8a33797c16c1cd8 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Sat, 27 Apr 2024 07:47:11 -0700 Subject: [PATCH 047/104] Increase recorder data limit Fixes #211530 --- src/vs/platform/terminal/common/terminalRecorder.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/platform/terminal/common/terminalRecorder.ts b/src/vs/platform/terminal/common/terminalRecorder.ts index d8fcb0269484b..79a828cc220a7 100644 --- a/src/vs/platform/terminal/common/terminalRecorder.ts +++ b/src/vs/platform/terminal/common/terminalRecorder.ts @@ -7,7 +7,7 @@ import { IPtyHostProcessReplayEvent } from 'vs/platform/terminal/common/capabili import { ReplayEntry } from 'vs/platform/terminal/common/terminalProcess'; const enum Constants { - MaxRecorderDataSize = 1024 * 1024 // 1MB + MaxRecorderDataSize = 10 * 1024 * 1024 // 10MB } interface RecorderEntry { From 9875c23cdea2bdd988264bed314bc37e5b4f6dd3 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Sat, 27 Apr 2024 08:04:47 -0700 Subject: [PATCH 048/104] shellIntegration.suggestEnabled -> suggest.enabled Part of #154662 --- src/vs/platform/terminal/common/terminal.ts | 4 +++- .../contrib/terminal/browser/terminal.contribution.ts | 2 +- .../contrib/terminal/browser/terminalProcessManager.ts | 4 ++-- src/vs/workbench/contrib/terminal/common/terminal.ts | 4 +++- .../contrib/terminal/common/terminalConfiguration.ts | 2 +- .../terminalContrib/suggest/browser/terminalSuggestAddon.ts | 2 +- 6 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/vs/platform/terminal/common/terminal.ts b/src/vs/platform/terminal/common/terminal.ts index 06d5d687dfc2f..54dd4eb5381b9 100644 --- a/src/vs/platform/terminal/common/terminal.ts +++ b/src/vs/platform/terminal/common/terminal.ts @@ -115,7 +115,6 @@ export const enum TerminalSettingId { ShellIntegrationShowWelcome = 'terminal.integrated.shellIntegration.showWelcome', ShellIntegrationDecorationsEnabled = 'terminal.integrated.shellIntegration.decorationsEnabled', ShellIntegrationCommandHistory = 'terminal.integrated.shellIntegration.history', - ShellIntegrationSuggestEnabled = 'terminal.integrated.shellIntegration.suggestEnabled', EnableImages = 'terminal.integrated.enableImages', SmoothScrolling = 'terminal.integrated.smoothScrolling', IgnoreBracketedPasteMode = 'terminal.integrated.ignoreBracketedPasteMode', @@ -126,6 +125,9 @@ export const enum TerminalSettingId { StickyScrollMaxLineCount = 'terminal.integrated.stickyScroll.maxLineCount', MouseWheelZoom = 'terminal.integrated.mouseWheelZoom', + // terminal.suggest.contribution + SuggestEnabled = 'terminal.integrated.suggest.enabled', + // Debug settings that are hidden from user /** Simulated latency applied to all calls made to the pty host */ diff --git a/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts b/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts index b9f06d1546f00..65d47616ddacd 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts @@ -206,7 +206,7 @@ registerSendSequenceKeybinding('\x1b[24~d', { // F12,d -> shift+end (SelectLine) mac: { primary: KeyMod.Shift | KeyMod.CtrlCmd | KeyCode.RightArrow } }); registerSendSequenceKeybinding('\x1b[24~e', { // F12,e -> ctrl+space (Native suggest) - when: ContextKeyExpr.and(TerminalContextKeys.focus, ContextKeyExpr.equals(TerminalContextKeyStrings.ShellType, WindowsShellType.PowerShell), TerminalContextKeys.terminalShellIntegrationEnabled, CONTEXT_ACCESSIBILITY_MODE_ENABLED.negate(), ContextKeyExpr.equals(`config.${TerminalSettingId.ShellIntegrationSuggestEnabled}`, true)), + when: ContextKeyExpr.and(TerminalContextKeys.focus, ContextKeyExpr.equals(TerminalContextKeyStrings.ShellType, WindowsShellType.PowerShell), TerminalContextKeys.terminalShellIntegrationEnabled, CONTEXT_ACCESSIBILITY_MODE_ENABLED.negate(), ContextKeyExpr.equals(`config.${TerminalSettingId.SuggestEnabled}`, true)), primary: KeyMod.CtrlCmd | KeyCode.Space, mac: { primary: KeyMod.WinCtrl | KeyCode.Space } }); diff --git a/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts b/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts index 2e51964baaf89..15374e6b2993b 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts @@ -285,7 +285,7 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce const options: ITerminalProcessOptions = { shellIntegration: { enabled: this._configurationService.getValue(TerminalSettingId.ShellIntegrationEnabled), - suggestEnabled: this._configurationService.getValue(TerminalSettingId.ShellIntegrationSuggestEnabled), + suggestEnabled: this._configurationService.getValue(TerminalSettingId.SuggestEnabled), nonce: this.shellIntegrationNonce }, windowsEnableConpty: this._terminalConfigurationService.config.windowsEnableConpty, @@ -485,7 +485,7 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce const options: ITerminalProcessOptions = { shellIntegration: { enabled: this._configurationService.getValue(TerminalSettingId.ShellIntegrationEnabled), - suggestEnabled: this._configurationService.getValue(TerminalSettingId.ShellIntegrationSuggestEnabled), + suggestEnabled: this._configurationService.getValue(TerminalSettingId.SuggestEnabled), nonce: this.shellIntegrationNonce }, windowsEnableConpty: this._terminalConfigurationService.config.windowsEnableConpty, diff --git a/src/vs/workbench/contrib/terminal/common/terminal.ts b/src/vs/workbench/contrib/terminal/common/terminal.ts index 71de8f0cceb65..e36e85d2f60c7 100644 --- a/src/vs/workbench/contrib/terminal/common/terminal.ts +++ b/src/vs/workbench/contrib/terminal/common/terminal.ts @@ -202,7 +202,9 @@ export interface ITerminalConfiguration { shellIntegration?: { enabled: boolean; decorationsEnabled: boolean; - suggestEnabled: boolean; + }; + suggest?: { + enabled: boolean; }; enableImages: boolean; smoothScrolling: boolean; diff --git a/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts b/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts index cb9ab6eb930f4..3960dcc0fcf16 100644 --- a/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts +++ b/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts @@ -627,7 +627,7 @@ const terminalConfiguration: IConfigurationNode = { type: 'number', default: 100 }, - [TerminalSettingId.ShellIntegrationSuggestEnabled]: { + [TerminalSettingId.SuggestEnabled]: { restricted: true, markdownDescription: localize('terminal.integrated.shellIntegration.suggestEnabled', "Enables experimental terminal Intellisense suggestions for supported shells when {0} is set to {1}. If shell integration is installed manually, {2} needs to be set to {3} before calling the script.", '`#terminal.integrated.shellIntegration.enabled#`', '`true`', '`VSCODE_SUGGEST`', '`1`'), type: 'boolean', diff --git a/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon.ts b/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon.ts index b8af40c5e618a..dd98319eed083 100644 --- a/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon.ts +++ b/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon.ts @@ -145,7 +145,7 @@ export class SuggestAddon extends Disposable implements ITerminalAddon, ISuggest } private _sync(promptInputState: IPromptInputModelState): void { - if (!this._terminalConfigurationService.config.shellIntegration?.suggestEnabled) { + if (!this._terminalConfigurationService.config.suggest?.enabled) { return; } From 5305ce56806f0d8939559ff443f6a6c113574349 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Sat, 27 Apr 2024 08:06:26 -0700 Subject: [PATCH 049/104] Order settings --- .../terminal/common/terminalConfiguration.ts | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts b/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts index 3960dcc0fcf16..7ccd21a472782 100644 --- a/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts +++ b/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts @@ -627,13 +627,6 @@ const terminalConfiguration: IConfigurationNode = { type: 'number', default: 100 }, - [TerminalSettingId.SuggestEnabled]: { - restricted: true, - markdownDescription: localize('terminal.integrated.shellIntegration.suggestEnabled', "Enables experimental terminal Intellisense suggestions for supported shells when {0} is set to {1}. If shell integration is installed manually, {2} needs to be set to {3} before calling the script.", '`#terminal.integrated.shellIntegration.enabled#`', '`true`', '`VSCODE_SUGGEST`', '`1`'), - type: 'boolean', - default: false, - markdownDeprecationMessage: localize('suggestEnabled.deprecated', 'This is an experimental setting and may break the terminal! Use at your own risk.') - }, [TerminalSettingId.SmoothScrolling]: { markdownDescription: localize('terminal.integrated.smoothScrolling', "Controls whether the terminal will scroll using an animation."), type: 'boolean', @@ -690,6 +683,15 @@ const terminalConfiguration: IConfigurationNode = { type: 'boolean', default: false }, + + // terminal.suggest.contribution + [TerminalSettingId.SuggestEnabled]: { + restricted: true, + markdownDescription: localize('terminal.integrated.suggest.enabled', "Enables experimental terminal Intellisense suggestions for supported shells when {0} is set to {1}. If shell integration is installed manually, {2} needs to be set to {3} before calling the script.", '`#terminal.integrated.shellIntegration.enabled#`', '`true`', '`VSCODE_SUGGEST`', '`1`'), + type: 'boolean', + default: false, + markdownDeprecationMessage: localize('suggestEnabled.deprecated', 'This is an experimental setting and may break the terminal! Use at your own risk.') + }, } }; From eb517dba14a0a4f3e714d458cd23e7ef3f06c2a0 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Sat, 27 Apr 2024 13:43:07 -0700 Subject: [PATCH 050/104] Don't add empty lines for removed content when copying chat message (#211541) --- src/vs/workbench/contrib/chat/common/chatModel.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/chat/common/chatModel.ts b/src/vs/workbench/contrib/chat/common/chatModel.ts index 9cf047a4b6a20..6c400c395acce 100644 --- a/src/vs/workbench/contrib/chat/common/chatModel.ts +++ b/src/vs/workbench/contrib/chat/common/chatModel.ts @@ -232,7 +232,9 @@ export class Response implements IResponse { } else { return part.content.value; } - }).join('\n\n'); + }) + .filter(s => s.length > 0) + .join('\n\n'); if (!quiet) { this._onDidChangeValue.fire(); From 877b634e29242a99ee01bb62a7dec449354b6886 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Sat, 27 Apr 2024 13:44:03 -0700 Subject: [PATCH 051/104] Normalize progress icon sizes (#211540) I don't know why I made just the checkmark smaller --- src/vs/workbench/contrib/chat/browser/media/chat.css | 1 - 1 file changed, 1 deletion(-) diff --git a/src/vs/workbench/contrib/chat/browser/media/chat.css b/src/vs/workbench/contrib/chat/browser/media/chat.css index 9058da7ea036d..d0a0a088e9c44 100644 --- a/src/vs/workbench/contrib/chat/browser/media/chat.css +++ b/src/vs/workbench/contrib/chat/browser/media/chat.css @@ -661,7 +661,6 @@ } .interactive-item-container .rendered-markdown.progress-step > p .codicon.codicon-check { - font-size: 14px; color: var(--vscode-debugIcon-startForeground) !important; } From 3012ebac4e47136115c5abc4f75aba8d9777e153 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Sat, 27 Apr 2024 13:45:26 -0700 Subject: [PATCH 052/104] Preserve original markdown string options when doing progressive render (#211539) Fix #1163 --- src/vs/workbench/contrib/chat/browser/chatListRenderer.ts | 7 ++++++- src/vs/workbench/contrib/chat/common/chatViewModel.ts | 2 ++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts b/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts index 641ebdb8407bd..d4133e7f8277d 100644 --- a/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts +++ b/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts @@ -619,6 +619,7 @@ export class ChatListItemRenderer extends Disposable implements ITreeRenderer Date: Sun, 28 Apr 2024 13:31:06 +0200 Subject: [PATCH 053/104] Fix wrong directory for Custom Editor Labels (#211523) * fixes #211522 * :lipstick: --- .../services/editor/common/customEditorLabelService.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/services/editor/common/customEditorLabelService.ts b/src/vs/workbench/services/editor/common/customEditorLabelService.ts index 3eb55a67968c5..8264adcbd91c0 100644 --- a/src/vs/workbench/services/editor/common/customEditorLabelService.ts +++ b/src/vs/workbench/services/editor/common/customEditorLabelService.ts @@ -139,7 +139,10 @@ export class CustomEditorLabelService extends Disposable implements ICustomEdito for (const pattern of this.patterns) { let relevantPath: string; if (root && !pattern.isAbsolutePath) { - relevantPath = relativePath ?? getRelativePath(resourceDirname(root.uri), resource) ?? resource.path; + if (!relativePath) { + relativePath = getRelativePath(resourceDirname(root.uri), resource) ?? resource.path; + } + relevantPath = relativePath; } else { relevantPath = resource.path; } @@ -186,7 +189,7 @@ export class CustomEditorLabelService extends Disposable implements ICustomEdito if (n < 0) { nth = Math.abs(n) - 1; } else { - nth = length - 1 - n - 1; // -1 for the filename, -1 for 0-based index + nth = length - n - 1; } const nthDir = pathFragments[nth]; From d211c56e2ac6526eeb1847505b582646c4f6754a Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Sun, 28 Apr 2024 04:42:56 -0700 Subject: [PATCH 054/104] Add back legacy setting while in dev --- src/vs/platform/terminal/common/terminal.ts | 1 + src/vs/workbench/contrib/terminal/common/terminal.ts | 2 ++ .../contrib/terminal/common/terminalConfiguration.ts | 8 +++++++- .../suggest/browser/terminalSuggestAddon.ts | 3 ++- 4 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/vs/platform/terminal/common/terminal.ts b/src/vs/platform/terminal/common/terminal.ts index 54dd4eb5381b9..6d95bef122e02 100644 --- a/src/vs/platform/terminal/common/terminal.ts +++ b/src/vs/platform/terminal/common/terminal.ts @@ -127,6 +127,7 @@ export const enum TerminalSettingId { // terminal.suggest.contribution SuggestEnabled = 'terminal.integrated.suggest.enabled', + SuggestEnabledLegacy = 'terminal.integrated.shellIntegration.suggestEnabled', // Debug settings that are hidden from user diff --git a/src/vs/workbench/contrib/terminal/common/terminal.ts b/src/vs/workbench/contrib/terminal/common/terminal.ts index f0fdef7aff8a3..d200bebe8ea69 100644 --- a/src/vs/workbench/contrib/terminal/common/terminal.ts +++ b/src/vs/workbench/contrib/terminal/common/terminal.ts @@ -202,6 +202,8 @@ export interface ITerminalConfiguration { shellIntegration?: { enabled: boolean; decorationsEnabled: boolean; + // TODO: Legacy - remove soon + suggestEnabled: boolean; }; suggest?: { enabled: boolean; diff --git a/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts b/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts index b61d13004e190..0dd762badf681 100644 --- a/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts +++ b/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts @@ -686,7 +686,13 @@ const terminalConfiguration: IConfigurationNode = { // terminal.suggest.contribution [TerminalSettingId.SuggestEnabled]: { restricted: true, - markdownDescription: localize('terminal.integrated.suggest.enabled', "Enables experimental terminal Intellisense suggestions for supported shells when {0} is set to {1}. If shell integration is installed manually, {2} needs to be set to {3} before calling the script.", '`#terminal.integrated.shellIntegration.enabled#`', '`true`', '`VSCODE_SUGGEST`', '`1`'), + markdownDescription: localize('terminal.integrated.suggest.enabled', "Enables experimental terminal Intellisense suggestions for supported shells when {0} is set to {1}. If shell integration is installed manually, {2} needs to be set to {3} before calling the script.", `\`#${TerminalSettingId.ShellIntegrationEnabled}#\``, '`true`', '`VSCODE_SUGGEST`', '`1`'), + type: 'boolean', + default: false, + }, + [TerminalSettingId.SuggestEnabledLegacy]: { + restricted: true, + markdownDescription: localize('terminal.integrated.suggest.enabled', "Enables experimental terminal Intellisense suggestions for supported shells when {0} is set to {1}. If shell integration is installed manually, {2} needs to be set to {3} before calling the script.", `\`#${TerminalSettingId.ShellIntegrationEnabled}#\``, '`true`', '`VSCODE_SUGGEST`', '`1`'), type: 'boolean', default: false, markdownDeprecationMessage: localize('suggestEnabled.deprecated', 'This is an experimental setting and may break the terminal! Use at your own risk.') diff --git a/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon.ts b/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon.ts index dd98319eed083..79b48d6a02b1a 100644 --- a/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon.ts +++ b/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon.ts @@ -145,7 +145,8 @@ export class SuggestAddon extends Disposable implements ITerminalAddon, ISuggest } private _sync(promptInputState: IPromptInputModelState): void { - if (!this._terminalConfigurationService.config.suggest?.enabled) { + const enabled = this._terminalConfigurationService.config.suggest?.enabled || this._terminalConfigurationService.config.shellIntegration?.enabled; + if (!enabled) { return; } From a21df121e4ed7e1dd374e21db38ba2154b7928b0 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Sun, 28 Apr 2024 04:47:35 -0700 Subject: [PATCH 055/104] Fix enablement of VSCODE_SUGGEST --- .../contrib/terminal/browser/terminalProcessManager.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts b/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts index 15374e6b2993b..3bb3f632c0721 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts @@ -285,7 +285,7 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce const options: ITerminalProcessOptions = { shellIntegration: { enabled: this._configurationService.getValue(TerminalSettingId.ShellIntegrationEnabled), - suggestEnabled: this._configurationService.getValue(TerminalSettingId.SuggestEnabled), + suggestEnabled: this._configurationService.getValue(TerminalSettingId.SuggestEnabled) || this._configurationService.getValue(TerminalSettingId.SuggestEnabledLegacy), nonce: this.shellIntegrationNonce }, windowsEnableConpty: this._terminalConfigurationService.config.windowsEnableConpty, @@ -485,7 +485,7 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce const options: ITerminalProcessOptions = { shellIntegration: { enabled: this._configurationService.getValue(TerminalSettingId.ShellIntegrationEnabled), - suggestEnabled: this._configurationService.getValue(TerminalSettingId.SuggestEnabled), + suggestEnabled: this._configurationService.getValue(TerminalSettingId.SuggestEnabled) || this._configurationService.getValue(TerminalSettingId.SuggestEnabledLegacy), nonce: this.shellIntegrationNonce }, windowsEnableConpty: this._terminalConfigurationService.config.windowsEnableConpty, From bd89581894ec157c29dc5e59e34ef12e0271f09a Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Sun, 28 Apr 2024 04:50:34 -0700 Subject: [PATCH 056/104] Improve suggest config description --- .../contrib/terminal/common/terminalConfiguration.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts b/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts index 0dd762badf681..00b271166e7ef 100644 --- a/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts +++ b/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts @@ -686,16 +686,16 @@ const terminalConfiguration: IConfigurationNode = { // terminal.suggest.contribution [TerminalSettingId.SuggestEnabled]: { restricted: true, - markdownDescription: localize('terminal.integrated.suggest.enabled', "Enables experimental terminal Intellisense suggestions for supported shells when {0} is set to {1}. If shell integration is installed manually, {2} needs to be set to {3} before calling the script.", `\`#${TerminalSettingId.ShellIntegrationEnabled}#\``, '`true`', '`VSCODE_SUGGEST`', '`1`'), + markdownDescription: localize('suggest.enabled', "Enables experimental terminal Intellisense suggestions for supported shells ({0}) when {1} is set to {2}.\n\nIf shell integration is installed manually, {3} needs to be set to {4} before calling the shell integration script.", 'PowerShell', `\`#${TerminalSettingId.ShellIntegrationEnabled}#\``, '`true`', '`VSCODE_SUGGEST`', '`1`'), type: 'boolean', default: false, }, [TerminalSettingId.SuggestEnabledLegacy]: { restricted: true, - markdownDescription: localize('terminal.integrated.suggest.enabled', "Enables experimental terminal Intellisense suggestions for supported shells when {0} is set to {1}. If shell integration is installed manually, {2} needs to be set to {3} before calling the script.", `\`#${TerminalSettingId.ShellIntegrationEnabled}#\``, '`true`', '`VSCODE_SUGGEST`', '`1`'), + markdownDescription: localize('suggest.enabled', "Enables experimental terminal Intellisense suggestions for supported shells ({0}) when {1} is set to {2}.\n\nIf shell integration is installed manually, {3} needs to be set to {4} before calling the shell integration script.", 'PowerShell', `\`#${TerminalSettingId.ShellIntegrationEnabled}#\``, '`true`', '`VSCODE_SUGGEST`', '`1`'), type: 'boolean', default: false, - markdownDeprecationMessage: localize('suggestEnabled.deprecated', 'This is an experimental setting and may break the terminal! Use at your own risk.') + markdownDeprecationMessage: localize('suggest.enabled.deprecated', 'This setting is deprecated, please use `{0}` instead.', `\`#${TerminalSettingId.SuggestEnabled}#\``) }, } }; From da654fb8f4e2b73641e53d71e055acd5619af94a Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Sun, 28 Apr 2024 05:05:07 -0700 Subject: [PATCH 057/104] Allow configuring terminal quick suggestions and on trigger chars Fixes #211533 --- src/vs/platform/terminal/common/terminal.ts | 2 ++ .../contrib/terminal/common/terminal.ts | 2 ++ .../terminal/common/terminalConfiguration.ts | 12 +++++++++++ .../suggest/browser/terminalSuggestAddon.ts | 20 ++++++++++++------- 4 files changed, 29 insertions(+), 7 deletions(-) diff --git a/src/vs/platform/terminal/common/terminal.ts b/src/vs/platform/terminal/common/terminal.ts index 6d95bef122e02..22fbfb7d555bd 100644 --- a/src/vs/platform/terminal/common/terminal.ts +++ b/src/vs/platform/terminal/common/terminal.ts @@ -128,6 +128,8 @@ export const enum TerminalSettingId { // terminal.suggest.contribution SuggestEnabled = 'terminal.integrated.suggest.enabled', SuggestEnabledLegacy = 'terminal.integrated.shellIntegration.suggestEnabled', + SuggestQuickSuggestions = 'terminal.integrated.suggest.quickSuggestions', + SuggestOnTriggerCharacters = 'terminal.integrated.suggest.suggestOnTriggerCharacters', // Debug settings that are hidden from user diff --git a/src/vs/workbench/contrib/terminal/common/terminal.ts b/src/vs/workbench/contrib/terminal/common/terminal.ts index d200bebe8ea69..49d846e5393ef 100644 --- a/src/vs/workbench/contrib/terminal/common/terminal.ts +++ b/src/vs/workbench/contrib/terminal/common/terminal.ts @@ -207,6 +207,8 @@ export interface ITerminalConfiguration { }; suggest?: { enabled: boolean; + quickSuggestions: boolean; + suggestOnTriggerCharacters: boolean; }; enableImages: boolean; smoothScrolling: boolean; diff --git a/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts b/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts index 00b271166e7ef..19038fd7343f3 100644 --- a/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts +++ b/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts @@ -697,6 +697,18 @@ const terminalConfiguration: IConfigurationNode = { default: false, markdownDeprecationMessage: localize('suggest.enabled.deprecated', 'This setting is deprecated, please use `{0}` instead.', `\`#${TerminalSettingId.SuggestEnabled}#\``) }, + [TerminalSettingId.SuggestQuickSuggestions]: { + restricted: true, + markdownDescription: localize('suggest.quickSuggestions', "Controls whether suggestions should automatically show up while typing. Also be aware of the {0}-setting which controls if suggestions are triggered by special characters.", `\`#${TerminalSettingId.SuggestOnTriggerCharacters}#\``), + type: 'boolean', + default: true, + }, + [TerminalSettingId.SuggestOnTriggerCharacters]: { + restricted: true, + markdownDescription: localize('suggest.suggestOnTriggerCharacters', "Controls whether suggestions should automatically show up when typing trigger characters."), + type: 'boolean', + default: true, + }, } }; diff --git a/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon.ts b/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon.ts index 79b48d6a02b1a..721f89b368b39 100644 --- a/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon.ts +++ b/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon.ts @@ -153,17 +153,23 @@ export class SuggestAddon extends Disposable implements ITerminalAddon, ISuggest if (!this._terminalSuggestWidgetVisibleContextKey.get()) { // If input has been added if (!this._mostRecentPromptInputState || promptInputState.cursorIndex > this._mostRecentPromptInputState.cursorIndex) { + let sent = false; + // Quick suggestions - if (promptInputState.cursorIndex === 1 || promptInputState.value.substring(0, promptInputState.cursorIndex).match(/\s[^\s]$/)) { - // TODO: Allow the user to configure terminal quickSuggestions - this._requestCompletions(); + if (this._terminalConfigurationService.config.suggest?.quickSuggestions) { + if (promptInputState.cursorIndex === 1 || promptInputState.value.substring(0, promptInputState.cursorIndex).match(/\s[^\s]$/)) { + this._requestCompletions(); + sent = true; + } } // Trigger characters - const lastChar = promptInputState.value.at(promptInputState.cursorIndex - 1); - if (lastChar?.match(/[\\\/\-]/)) { - // TODO: Allow the user to configure terminal suggestOnTriggerCharacters - this._requestCompletions(); + if (this._terminalConfigurationService.config.suggest?.suggestOnTriggerCharacters && !sent) { + const lastChar = promptInputState.value.at(promptInputState.cursorIndex - 1); + if (lastChar?.match(/[\\\/\-]/)) { + this._requestCompletions(); + sent = true; + } } } } From 3e3270e442f507bc7ecb17bcaa5d2c5311905876 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Sun, 28 Apr 2024 05:29:09 -0700 Subject: [PATCH 058/104] Move terminal sticky scroll config into terminalContrib Part of #211569 --- src/vs/platform/terminal/common/terminal.ts | 2 - .../terminal/browser/terminalActions.ts | 18 -------- .../browser/xterm/markNavigationAddon.ts | 7 ++- .../contrib/terminal/common/terminal.ts | 1 - .../terminal/common/terminalConfiguration.ts | 17 +++---- .../terminal/common/terminalStrings.ts | 1 - .../terminal.stickyScroll.contribution.ts | 44 ++++++++++++++++++- .../terminalStickyScrollColorRegistry.ts | 3 +- .../terminalStickyScrollContribution.ts | 6 +-- .../browser/terminalStickyScrollOverlay.ts | 6 +-- .../terminalStickyScrollConfiguration.ts | 34 ++++++++++++++ 11 files changed, 93 insertions(+), 46 deletions(-) create mode 100644 src/vs/workbench/contrib/terminalContrib/stickyScroll/common/terminalStickyScrollConfiguration.ts diff --git a/src/vs/platform/terminal/common/terminal.ts b/src/vs/platform/terminal/common/terminal.ts index 06d5d687dfc2f..4bae713de7e07 100644 --- a/src/vs/platform/terminal/common/terminal.ts +++ b/src/vs/platform/terminal/common/terminal.ts @@ -122,8 +122,6 @@ export const enum TerminalSettingId { FocusAfterRun = 'terminal.integrated.focusAfterRun', AccessibleViewPreserveCursorPosition = 'terminal.integrated.accessibleViewPreserveCursorPosition', AccessibleViewFocusOnCommandExecution = 'terminal.integrated.accessibleViewFocusOnCommandExecution', - StickyScrollEnabled = 'terminal.integrated.stickyScroll.enabled', - StickyScrollMaxLineCount = 'terminal.integrated.stickyScroll.maxLineCount', MouseWheelZoom = 'terminal.integrated.mouseWheelZoom', // Debug settings that are hidden from user diff --git a/src/vs/workbench/contrib/terminal/browser/terminalActions.ts b/src/vs/workbench/contrib/terminal/browser/terminalActions.ts index 1166023453d13..f4f0233b5cc5b 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalActions.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalActions.ts @@ -1520,24 +1520,6 @@ export function registerTerminalActions() { } }); - registerTerminalAction({ - id: TerminalCommandId.ToggleStickyScroll, - title: localize2('workbench.action.terminal.toggleStickyScroll', 'Toggle Sticky Scroll'), - toggled: { - condition: ContextKeyExpr.equals('config.terminal.integrated.stickyScroll.enabled', true), - title: localize('stickyScroll', "Sticky Scroll"), - mnemonicTitle: localize({ key: 'miStickyScroll', comment: ['&& denotes a mnemonic'] }, "&&Sticky Scroll"), - }, - run: (c, accessor) => { - const configurationService = accessor.get(IConfigurationService); - const newValue = !configurationService.getValue(TerminalSettingId.StickyScrollEnabled); - return configurationService.updateValue(TerminalSettingId.StickyScrollEnabled, newValue); - }, - menu: [ - { id: MenuId.TerminalStickyScrollContext } - ] - }); - // Some commands depend on platform features if (BrowserFeatures.clipboard.writeText) { registerActiveXtermAction({ diff --git a/src/vs/workbench/contrib/terminal/browser/xterm/markNavigationAddon.ts b/src/vs/workbench/contrib/terminal/browser/xterm/markNavigationAddon.ts index e0d8a498fa3c5..0c0048cc757f1 100644 --- a/src/vs/workbench/contrib/terminal/browser/xterm/markNavigationAddon.ts +++ b/src/vs/workbench/contrib/terminal/browser/xterm/markNavigationAddon.ts @@ -14,7 +14,10 @@ import { TERMINAL_OVERVIEW_RULER_CURSOR_FOREGROUND_COLOR } from 'vs/workbench/co import { getWindow } from 'vs/base/browser/dom'; import { ICurrentPartialCommand } from 'vs/platform/terminal/common/capabilities/commandDetection/terminalCommand'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { TerminalSettingId } from 'vs/platform/terminal/common/terminal'; + +// HACK: Mark navigation currently depends on terminalContrib/stickyScroll +// eslint-disable-next-line local/code-import-patterns +import { TerminalStickyScrollSettingId } from 'vs/workbench/contrib/terminalContrib/stickyScroll/common/terminalStickyScrollConfiguration'; enum Boundary { Top, @@ -282,7 +285,7 @@ export class MarkNavigationAddon extends Disposable implements IMarkTracker, ITe { bufferRange: range, // Ensure scroll shows the line when sticky scroll is enabled - forceScroll: !!this._configurationService.getValue(TerminalSettingId.StickyScrollEnabled) + forceScroll: !!this._configurationService.getValue(TerminalStickyScrollSettingId.Enabled) } ); } diff --git a/src/vs/workbench/contrib/terminal/common/terminal.ts b/src/vs/workbench/contrib/terminal/common/terminal.ts index 8f4d1d85dab7b..5da54ba16257f 100644 --- a/src/vs/workbench/contrib/terminal/common/terminal.ts +++ b/src/vs/workbench/contrib/terminal/common/terminal.ts @@ -498,7 +498,6 @@ export const enum TerminalCommandId { HideSuggestWidget = 'workbench.action.terminal.hideSuggestWidget', FocusHover = 'workbench.action.terminal.focusHover', ShowEnvironmentContributions = 'workbench.action.terminal.showEnvironmentContributions', - ToggleStickyScroll = 'workbench.action.terminal.toggleStickyScroll', StartVoice = 'workbench.action.terminal.startVoice', StopVoice = 'workbench.action.terminal.stopVoice', FontZoomIn = 'workbench.action.terminal.fontZoomIn', diff --git a/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts b/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts index a3e4b8dd2de0a..1c44bfbeeef83 100644 --- a/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts +++ b/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts @@ -14,6 +14,10 @@ import { terminalColorSchema, terminalIconSchema } from 'vs/platform/terminal/co import product from 'vs/platform/product/common/product'; import { Extensions as WorkbenchExtensions, IConfigurationMigrationRegistry, ConfigurationKeyValuePairs } from 'vs/workbench/common/configuration'; +// Import configuration schemes from terminalContrib - this is an exception to the eslint rule since +// they need to be declared at part of the rest of the terminal configuration +import { terminalStickyScrollConfiguration } from 'vs/workbench/contrib/terminalContrib/stickyScroll/common/terminalStickyScrollConfiguration'; // eslint-disable-line local/code-import-patterns + const terminalDescriptors = '\n- ' + [ '`\${cwd}`: ' + localize("cwd", "the terminal's current working directory"), '`\${cwdFolder}`: ' + localize('cwdFolder', "the terminal's current working directory, displayed for multi-root workspaces or in a single root workspace when the value differs from the initial working directory. On Windows, this will only be displayed when shell integration is enabled."), @@ -670,18 +674,6 @@ const terminalConfiguration: IConfigurationNode = { type: 'boolean', default: false }, - [TerminalSettingId.StickyScrollEnabled]: { - markdownDescription: localize('terminal.integrated.stickyScroll.enabled', "Shows the current command at the top of the terminal."), - type: 'boolean', - default: product.quality !== 'stable' - }, - [TerminalSettingId.StickyScrollMaxLineCount]: { - markdownDescription: localize('terminal.integrated.stickyScroll.maxLineCount', "Defines the maximum number of sticky lines to show. Sticky scroll lines will never exceed 40% of the viewport regardless of this setting."), - type: 'number', - default: 5, - minimum: 1, - maximum: 10 - }, [TerminalSettingId.MouseWheelZoom]: { markdownDescription: isMacintosh ? localize('terminal.integrated.mouseWheelZoom.mac', "Zoom the font of the terminal when using mouse wheel and holding `Cmd`.") @@ -689,6 +681,7 @@ const terminalConfiguration: IConfigurationNode = { type: 'boolean', default: false }, + ...terminalStickyScrollConfiguration } }; diff --git a/src/vs/workbench/contrib/terminal/common/terminalStrings.ts b/src/vs/workbench/contrib/terminal/common/terminalStrings.ts index a8602f7d2f6de..7b726a7c1d888 100644 --- a/src/vs/workbench/contrib/terminal/common/terminalStrings.ts +++ b/src/vs/workbench/contrib/terminal/common/terminalStrings.ts @@ -39,7 +39,6 @@ export const terminalStrings = { sendSequence: localize2('workbench.action.terminal.sendSequence', "Send Custom Sequence To Terminal"), newWithCwd: localize2('workbench.action.terminal.newWithCwd', "Create New Terminal Starting in a Custom Working Directory"), renameWithArgs: localize2('workbench.action.terminal.renameWithArg', "Rename the Currently Active Terminal"), - stickyScroll: localize2('stickyScroll', "Sticky Scroll"), scrollToPreviousCommand: localize2('workbench.action.terminal.scrollToPreviousCommand', "Scroll To Previous Command"), scrollToNextCommand: localize2('workbench.action.terminal.scrollToNextCommand', "Scroll To Next Command") }; diff --git a/src/vs/workbench/contrib/terminalContrib/stickyScroll/browser/terminal.stickyScroll.contribution.ts b/src/vs/workbench/contrib/terminalContrib/stickyScroll/browser/terminal.stickyScroll.contribution.ts index 93a1102635457..cfac60baf6379 100644 --- a/src/vs/workbench/contrib/terminalContrib/stickyScroll/browser/terminal.stickyScroll.contribution.ts +++ b/src/vs/workbench/contrib/terminalContrib/stickyScroll/browser/terminal.stickyScroll.contribution.ts @@ -3,10 +3,50 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import 'vs/css!./media/stickyScroll'; +import { localize, localize2 } from 'vs/nls'; +import { MenuId } from 'vs/platform/actions/common/actions'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; +import { registerTerminalAction } from 'vs/workbench/contrib/terminal/browser/terminalActions'; import { registerTerminalContribution } from 'vs/workbench/contrib/terminal/browser/terminalExtensions'; import { TerminalStickyScrollContribution } from 'vs/workbench/contrib/terminalContrib/stickyScroll/browser/terminalStickyScrollContribution'; +import { TerminalStickyScrollSettingId } from 'vs/workbench/contrib/terminalContrib/stickyScroll/common/terminalStickyScrollConfiguration'; -import 'vs/css!./media/stickyScroll'; -import './terminalStickyScrollColorRegistry'; +// #region Contributions registerTerminalContribution(TerminalStickyScrollContribution.ID, TerminalStickyScrollContribution, true); + +// #endregion + +// #region Actions + +const enum TerminalStickyScrollCommandId { + ToggleStickyScroll = 'workbench.action.terminal.toggleStickyScroll', +} + +registerTerminalAction({ + id: TerminalStickyScrollCommandId.ToggleStickyScroll, + title: localize2('workbench.action.terminal.toggleStickyScroll', 'Toggle Sticky Scroll'), + toggled: { + condition: ContextKeyExpr.equals(`config.${TerminalStickyScrollSettingId.Enabled}`, true), + title: localize('stickyScroll', "Sticky Scroll"), + mnemonicTitle: localize({ key: 'miStickyScroll', comment: ['&& denotes a mnemonic'] }, "&&Sticky Scroll"), + }, + run: (c, accessor) => { + const configurationService = accessor.get(IConfigurationService); + const newValue = !configurationService.getValue(TerminalStickyScrollSettingId.Enabled); + return configurationService.updateValue(TerminalStickyScrollSettingId.Enabled, newValue); + }, + menu: [ + { id: MenuId.TerminalStickyScrollContext } + ] +}); + +// #endregion + +// #region Colors + +import './terminalStickyScrollColorRegistry'; + +// #endregion diff --git a/src/vs/workbench/contrib/terminalContrib/stickyScroll/browser/terminalStickyScrollColorRegistry.ts b/src/vs/workbench/contrib/terminalContrib/stickyScroll/browser/terminalStickyScrollColorRegistry.ts index 3fb4a9f9322d6..5ab1af0d0eb3c 100644 --- a/src/vs/workbench/contrib/terminalContrib/stickyScroll/browser/terminalStickyScrollColorRegistry.ts +++ b/src/vs/workbench/contrib/terminalContrib/stickyScroll/browser/terminalStickyScrollColorRegistry.ts @@ -4,9 +4,8 @@ *--------------------------------------------------------------------------------------------*/ import { Color } from 'vs/base/common/color'; -import 'vs/css!./media/stickyScroll'; import { localize } from 'vs/nls'; -import { registerColor } from 'vs/platform/theme/common/colorRegistry'; +import { registerColor } from 'vs/platform/theme/common/colorUtils'; export const terminalStickyScrollBackground = registerColor('terminalStickyScroll.background', { light: null, diff --git a/src/vs/workbench/contrib/terminalContrib/stickyScroll/browser/terminalStickyScrollContribution.ts b/src/vs/workbench/contrib/terminalContrib/stickyScroll/browser/terminalStickyScrollContribution.ts index a3730a5300469..69a38b8142e40 100644 --- a/src/vs/workbench/contrib/terminalContrib/stickyScroll/browser/terminalStickyScrollContribution.ts +++ b/src/vs/workbench/contrib/terminalContrib/stickyScroll/browser/terminalStickyScrollContribution.ts @@ -12,11 +12,11 @@ import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities'; -import { TerminalSettingId } from 'vs/platform/terminal/common/terminal'; import { ITerminalContribution, ITerminalInstance, IXtermTerminal } from 'vs/workbench/contrib/terminal/browser/terminal'; import { TerminalInstance, TerminalInstanceColorProvider } from 'vs/workbench/contrib/terminal/browser/terminalInstance'; import { TerminalWidgetManager } from 'vs/workbench/contrib/terminal/browser/widgets/widgetManager'; import { ITerminalProcessInfo, ITerminalProcessManager } from 'vs/workbench/contrib/terminal/common/terminal'; +import { TerminalStickyScrollSettingId } from 'vs/workbench/contrib/terminalContrib/stickyScroll/common/terminalStickyScrollConfiguration'; import { TerminalStickyScrollOverlay } from 'vs/workbench/contrib/terminalContrib/stickyScroll/browser/terminalStickyScrollOverlay'; export class TerminalStickyScrollContribution extends Disposable implements ITerminalContribution { @@ -45,7 +45,7 @@ export class TerminalStickyScrollContribution extends Disposable implements ITer super(); this._register(Event.runAndSubscribe(this._configurationService.onDidChangeConfiguration, e => { - if (!e || e.affectsConfiguration(TerminalSettingId.StickyScrollEnabled)) { + if (!e || e.affectsConfiguration(TerminalStickyScrollSettingId.Enabled)) { this._refreshState(); } })); @@ -118,6 +118,6 @@ export class TerminalStickyScrollContribution extends Disposable implements ITer private _shouldBeEnabled(): boolean { const capability = this._instance.capabilities.get(TerminalCapability.CommandDetection); - return !!(this._configurationService.getValue(TerminalSettingId.StickyScrollEnabled) && capability && this._xterm?.raw?.element); + return !!(this._configurationService.getValue(TerminalStickyScrollSettingId.Enabled) && capability && this._xterm?.raw?.element); } } diff --git a/src/vs/workbench/contrib/terminalContrib/stickyScroll/browser/terminalStickyScrollOverlay.ts b/src/vs/workbench/contrib/terminalContrib/stickyScroll/browser/terminalStickyScrollOverlay.ts index b5d59cb1ea670..194ee23694e42 100644 --- a/src/vs/workbench/contrib/terminalContrib/stickyScroll/browser/terminalStickyScrollOverlay.ts +++ b/src/vs/workbench/contrib/terminalContrib/stickyScroll/browser/terminalStickyScrollOverlay.ts @@ -20,13 +20,13 @@ import { IContextMenuService } from 'vs/platform/contextview/browser/contextView import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { ICommandDetectionCapability, ITerminalCommand } from 'vs/platform/terminal/common/capabilities/capabilities'; import { ICurrentPartialCommand } from 'vs/platform/terminal/common/capabilities/commandDetection/terminalCommand'; -import { TerminalSettingId } from 'vs/platform/terminal/common/terminal'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { ITerminalInstance, IXtermColorProvider, IXtermTerminal } from 'vs/workbench/contrib/terminal/browser/terminal'; import { openContextMenu } from 'vs/workbench/contrib/terminal/browser/terminalContextMenu'; import { IXtermCore } from 'vs/workbench/contrib/terminal/browser/xterm-private'; import { TERMINAL_CONFIG_SECTION, TerminalCommandId } from 'vs/workbench/contrib/terminal/common/terminal'; import { terminalStrings } from 'vs/workbench/contrib/terminal/common/terminalStrings'; +import { TerminalStickyScrollSettingId } from 'vs/workbench/contrib/terminalContrib/stickyScroll/common/terminalStickyScrollConfiguration'; import { terminalStickyScrollBackground, terminalStickyScrollHoverBackground } from 'vs/workbench/contrib/terminalContrib/stickyScroll/browser/terminalStickyScrollColorRegistry'; const enum OverlayState { @@ -82,8 +82,8 @@ export class TerminalStickyScrollOverlay extends Disposable { // React to configuration changes this._register(Event.runAndSubscribe(configurationService.onDidChangeConfiguration, e => { - if (!e || e.affectsConfiguration(TerminalSettingId.StickyScrollMaxLineCount)) { - this._rawMaxLineCount = configurationService.getValue(TerminalSettingId.StickyScrollMaxLineCount); + if (!e || e.affectsConfiguration(TerminalStickyScrollSettingId.MaxLineCount)) { + this._rawMaxLineCount = configurationService.getValue(TerminalStickyScrollSettingId.MaxLineCount); } })); diff --git a/src/vs/workbench/contrib/terminalContrib/stickyScroll/common/terminalStickyScrollConfiguration.ts b/src/vs/workbench/contrib/terminalContrib/stickyScroll/common/terminalStickyScrollConfiguration.ts new file mode 100644 index 0000000000000..8e9c34d32f401 --- /dev/null +++ b/src/vs/workbench/contrib/terminalContrib/stickyScroll/common/terminalStickyScrollConfiguration.ts @@ -0,0 +1,34 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import type { IStringDictionary } from 'vs/base/common/collections'; +import { localize } from 'vs/nls'; +import type { IConfigurationPropertySchema } from 'vs/platform/configuration/common/configurationRegistry'; +import product from 'vs/platform/product/common/product'; + +export const enum TerminalStickyScrollSettingId { + Enabled = 'terminal.integrated.stickyScroll.enabled', + MaxLineCount = 'terminal.integrated.stickyScroll.maxLineCount', +} + +export interface ITerminalStickyScrollConfiguration { + enabled: boolean; + maxLineCount: number; +} + +export const terminalStickyScrollConfiguration: IStringDictionary = { + [TerminalStickyScrollSettingId.Enabled]: { + markdownDescription: localize('stickyScroll.enabled', "Shows the current command at the top of the terminal."), + type: 'boolean', + default: product.quality !== 'stable' + }, + [TerminalStickyScrollSettingId.MaxLineCount]: { + markdownDescription: localize('stickyScroll.maxLineCount', "Defines the maximum number of sticky lines to show. Sticky scroll lines will never exceed 40% of the viewport regardless of this setting."), + type: 'number', + default: 5, + minimum: 1, + maximum: 10 + }, +}; From 62d7fb62d2978fcacf196f1036c38ed40c814033 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Sun, 28 Apr 2024 05:39:33 -0700 Subject: [PATCH 059/104] Fix enabled check --- .../workbench/contrib/terminal/browser/terminal.contribution.ts | 2 +- .../terminalContrib/suggest/browser/terminalSuggestAddon.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts b/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts index 65d47616ddacd..1a2444f223908 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts @@ -206,7 +206,7 @@ registerSendSequenceKeybinding('\x1b[24~d', { // F12,d -> shift+end (SelectLine) mac: { primary: KeyMod.Shift | KeyMod.CtrlCmd | KeyCode.RightArrow } }); registerSendSequenceKeybinding('\x1b[24~e', { // F12,e -> ctrl+space (Native suggest) - when: ContextKeyExpr.and(TerminalContextKeys.focus, ContextKeyExpr.equals(TerminalContextKeyStrings.ShellType, WindowsShellType.PowerShell), TerminalContextKeys.terminalShellIntegrationEnabled, CONTEXT_ACCESSIBILITY_MODE_ENABLED.negate(), ContextKeyExpr.equals(`config.${TerminalSettingId.SuggestEnabled}`, true)), + when: ContextKeyExpr.and(TerminalContextKeys.focus, ContextKeyExpr.equals(TerminalContextKeyStrings.ShellType, WindowsShellType.PowerShell), TerminalContextKeys.terminalShellIntegrationEnabled, CONTEXT_ACCESSIBILITY_MODE_ENABLED.negate(), ContextKeyExpr.or(ContextKeyExpr.equals(`config.${TerminalSettingId.SuggestEnabled}`, true), ContextKeyExpr.equals(`config.${TerminalSettingId.SuggestEnabledLegacy}`, true))), primary: KeyMod.CtrlCmd | KeyCode.Space, mac: { primary: KeyMod.WinCtrl | KeyCode.Space } }); diff --git a/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon.ts b/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon.ts index 79b48d6a02b1a..1c8f446b59f79 100644 --- a/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon.ts +++ b/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon.ts @@ -145,7 +145,7 @@ export class SuggestAddon extends Disposable implements ITerminalAddon, ISuggest } private _sync(promptInputState: IPromptInputModelState): void { - const enabled = this._terminalConfigurationService.config.suggest?.enabled || this._terminalConfigurationService.config.shellIntegration?.enabled; + const enabled = this._terminalConfigurationService.config.suggest?.enabled || this._terminalConfigurationService.config.shellIntegration?.suggestEnabled; if (!enabled) { return; } From 04d9b9e4e51e7763a73f1a1d2afb708d82465375 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Sun, 28 Apr 2024 05:45:04 -0700 Subject: [PATCH 060/104] More more terminal quick fix code into terminalContrib --- .../browser/xterm/decorationStyles.ts | 1 - .../contrib/terminal/common/terminal.ts | 1 - .../quickFix/browser/quickFixAddon.ts | 8 +++++-- .../browser/terminal.quickFix.contribution.ts | 23 +++++++++++++++---- 4 files changed, 24 insertions(+), 9 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/browser/xterm/decorationStyles.ts b/src/vs/workbench/contrib/terminal/browser/xterm/decorationStyles.ts index e2ada5a5a1053..1e82b5badc317 100644 --- a/src/vs/workbench/contrib/terminal/browser/xterm/decorationStyles.ts +++ b/src/vs/workbench/contrib/terminal/browser/xterm/decorationStyles.ts @@ -29,7 +29,6 @@ export const enum DecorationSelector { Codicon = 'codicon', XtermDecoration = 'xterm-decoration', OverviewRuler = '.xterm-decoration-overview-ruler', - QuickFix = 'quick-fix' } export class TerminalDecorationHoverManager extends Disposable { diff --git a/src/vs/workbench/contrib/terminal/common/terminal.ts b/src/vs/workbench/contrib/terminal/common/terminal.ts index 5da54ba16257f..90ef2ea8f8b65 100644 --- a/src/vs/workbench/contrib/terminal/common/terminal.ts +++ b/src/vs/workbench/contrib/terminal/common/terminal.ts @@ -426,7 +426,6 @@ export const enum TerminalCommandId { Split = 'workbench.action.terminal.split', SplitActiveTab = 'workbench.action.terminal.splitActiveTab', SplitInActiveWorkspace = 'workbench.action.terminal.splitInActiveWorkspace', - ShowQuickFixes = 'workbench.action.terminal.showQuickFixes', Unsplit = 'workbench.action.terminal.unsplit', JoinActiveTab = 'workbench.action.terminal.joinActiveTab', Join = 'workbench.action.terminal.join', diff --git a/src/vs/workbench/contrib/terminalContrib/quickFix/browser/quickFixAddon.ts b/src/vs/workbench/contrib/terminalContrib/quickFix/browser/quickFixAddon.ts index 21c627770546a..9444cf1090b1e 100644 --- a/src/vs/workbench/contrib/terminalContrib/quickFix/browser/quickFixAddon.ts +++ b/src/vs/workbench/contrib/terminalContrib/quickFix/browser/quickFixAddon.ts @@ -36,8 +36,12 @@ import { Codicon } from 'vs/base/common/codicons'; import { ThemeIcon } from 'vs/base/common/themables'; import { ICommandService } from 'vs/platform/commands/common/commands'; +const enum QuickFixDecorationSelector { + QuickFix = 'quick-fix' +} + const quickFixClasses = [ - DecorationSelector.QuickFix, + QuickFixDecorationSelector.QuickFix, DecorationSelector.Codicon, DecorationSelector.CommandDecoration, DecorationSelector.XtermDecoration @@ -268,7 +272,7 @@ export class TerminalQuickFixAddon extends Disposable implements ITerminalAddon, height: rect.height }; - if (e.classList.contains(DecorationSelector.QuickFix)) { + if (e.classList.contains(QuickFixDecorationSelector.QuickFix)) { if (this._currentRenderContext) { this._currentRenderContext.anchor = anchor; } 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 faa206bdcc28f..9533aa208d50f 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 @@ -14,7 +14,7 @@ import { ITerminalContribution, ITerminalInstance, IXtermTerminal } from 'vs/wor import { registerActiveInstanceAction } from 'vs/workbench/contrib/terminal/browser/terminalActions'; import { registerTerminalContribution } from 'vs/workbench/contrib/terminal/browser/terminalExtensions'; import { TerminalWidgetManager } from 'vs/workbench/contrib/terminal/browser/widgets/widgetManager'; -import { ITerminalProcessManager, TerminalCommandId } from 'vs/workbench/contrib/terminal/common/terminal'; +import { ITerminalProcessManager } from 'vs/workbench/contrib/terminal/common/terminal'; import { TerminalContextKeys } from 'vs/workbench/contrib/terminal/common/terminalContextKey'; import { ITerminalQuickFixService } from 'vs/workbench/contrib/terminalContrib/quickFix/browser/quickFix'; import { TerminalQuickFixAddon } from 'vs/workbench/contrib/terminalContrib/quickFix/browser/quickFixAddon'; @@ -22,10 +22,14 @@ import { freePort, gitCreatePr, gitPull, gitPushSetUpstream, gitSimilar, gitTwoD import { TerminalQuickFixService } from 'vs/workbench/contrib/terminalContrib/quickFix/browser/terminalQuickFixService'; import type { Terminal as RawXtermTerminal } from '@xterm/xterm'; -// Services +// #region Services + registerSingleton(ITerminalQuickFixService, TerminalQuickFixService, InstantiationType.Delayed); -// Contributions +// #endregion + +// #region Contributions + class TerminalQuickFixContribution extends DisposableStore implements ITerminalContribution { static readonly ID = 'quickFix'; @@ -70,9 +74,16 @@ class TerminalQuickFixContribution extends DisposableStore implements ITerminalC } registerTerminalContribution(TerminalQuickFixContribution.ID, TerminalQuickFixContribution); -// Actions +// #endregion + +// #region Actions + +const enum TerminalQuickFixCommandId { + ShowQuickFixes = 'workbench.action.terminal.showQuickFixes', +} + registerActiveInstanceAction({ - id: TerminalCommandId.ShowQuickFixes, + id: TerminalQuickFixCommandId.ShowQuickFixes, title: localize2('workbench.action.terminal.showQuickFixes', 'Show Terminal Quick Fixes'), precondition: TerminalContextKeys.focus, keybinding: { @@ -81,3 +92,5 @@ registerActiveInstanceAction({ }, run: (activeInstance) => TerminalQuickFixContribution.get(activeInstance)?.addon?.showMenu() }); + +// #endregion From a544191290f4a7429c52713a1bcdb978515d9752 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Sun, 28 Apr 2024 05:58:10 -0700 Subject: [PATCH 061/104] More more terminal a11y code into terminalContrib --- src/vs/platform/terminal/common/terminal.ts | 2 -- .../terminal/browser/terminalInstance.ts | 6 +++- .../contrib/terminal/common/terminal.ts | 11 +++---- .../terminal/common/terminalConfiguration.ts | 12 ++----- .../terminal.accessibility.contribution.ts | 29 ++++++++++------- .../browser/terminalAccessibilityHelp.ts | 12 ++++--- .../terminalAccessibleBufferProvider.ts | 8 ++--- .../common/terminal.accessibility.ts | 16 ++++++++++ .../terminalAccessibilityConfiguration.ts | 31 +++++++++++++++++++ 9 files changed, 88 insertions(+), 39 deletions(-) create mode 100644 src/vs/workbench/contrib/terminalContrib/accessibility/common/terminal.accessibility.ts create mode 100644 src/vs/workbench/contrib/terminalContrib/accessibility/common/terminalAccessibilityConfiguration.ts diff --git a/src/vs/platform/terminal/common/terminal.ts b/src/vs/platform/terminal/common/terminal.ts index 4bae713de7e07..eb7f36e8b792a 100644 --- a/src/vs/platform/terminal/common/terminal.ts +++ b/src/vs/platform/terminal/common/terminal.ts @@ -120,8 +120,6 @@ export const enum TerminalSettingId { SmoothScrolling = 'terminal.integrated.smoothScrolling', IgnoreBracketedPasteMode = 'terminal.integrated.ignoreBracketedPasteMode', FocusAfterRun = 'terminal.integrated.focusAfterRun', - AccessibleViewPreserveCursorPosition = 'terminal.integrated.accessibleViewPreserveCursorPosition', - AccessibleViewFocusOnCommandExecution = 'terminal.integrated.accessibleViewFocusOnCommandExecution', MouseWheelZoom = 'terminal.integrated.mouseWheelZoom', // Debug settings that are hidden from user diff --git a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts index a53fb826303cb..b776bce1487e1 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts @@ -89,6 +89,10 @@ import { terminalStrings } from 'vs/workbench/contrib/terminal/common/terminalSt import { shouldPasteTerminalText } from 'vs/workbench/contrib/terminal/common/terminalClipboard'; import { TerminalIconPicker } from 'vs/workbench/contrib/terminal/browser/terminalIconPicker'; +// HACK: This file should not depend on terminalContrib +// eslint-disable-next-line local/code-import-patterns +import { TerminalAccessibilityCommandId } from 'vs/workbench/contrib/terminalContrib/accessibility/common/terminal.accessibility'; + const enum Constants { /** * The maximum amount of milliseconds to wait for a container before starting to create the @@ -702,7 +706,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { get shouldPersist(): boolean { return this._processManager.shouldPersist && !this.shellLaunchConfig.isTransient && (!this.reconnectionProperties || this._configurationService.getValue('task.reconnection') === true); } public static getXtermConstructor(keybindingService: IKeybindingService, contextKeyService: IContextKeyService) { - const keybinding = keybindingService.lookupKeybinding(TerminalCommandId.FocusAccessibleBuffer, contextKeyService); + const keybinding = keybindingService.lookupKeybinding(TerminalAccessibilityCommandId.FocusAccessibleBuffer, contextKeyService); if (xtermConstructor) { return xtermConstructor; } diff --git a/src/vs/workbench/contrib/terminal/common/terminal.ts b/src/vs/workbench/contrib/terminal/common/terminal.ts index 90ef2ea8f8b65..8583343525903 100644 --- a/src/vs/workbench/contrib/terminal/common/terminal.ts +++ b/src/vs/workbench/contrib/terminal/common/terminal.ts @@ -19,6 +19,10 @@ import { AccessibilityCommandId } from 'vs/workbench/contrib/accessibility/commo import { IEnvironmentVariableInfo } from 'vs/workbench/contrib/terminal/common/environmentVariable'; import { IExtensionPointDescriptor } from 'vs/workbench/services/extensions/common/extensionsRegistry'; +// Import commands to skip shell from terminalContrib - this is an exception to the eslint rule +// since they need to be included in the terminal module +import { defaultTerminalAccessibilityCommandsToSkipShell } from 'vs/workbench/contrib/terminalContrib/accessibility/browser/terminal.accessibility'; // eslint-disable-line local/code-import-patterns + export const TERMINAL_VIEW_ID = 'terminal'; export const TERMINAL_CREATION_COMMANDS = ['workbench.action.terminal.toggleTerminal', 'workbench.action.terminal.new', 'workbench.action.togglePanel', 'workbench.action.terminal.focus']; @@ -402,9 +406,6 @@ export const enum TerminalCommandId { OpenFileLink = 'workbench.action.terminal.openFileLink', OpenWebLink = 'workbench.action.terminal.openUrlLink', RunRecentCommand = 'workbench.action.terminal.runRecentCommand', - FocusAccessibleBuffer = 'workbench.action.terminal.focusAccessibleBuffer', - AccessibleBufferGoToNextCommand = 'workbench.action.terminal.accessibleBufferGoToNextCommand', - AccessibleBufferGoToPreviousCommand = 'workbench.action.terminal.accessibleBufferGoToPreviousCommand', CopyLastCommand = 'workbench.action.terminal.copyLastCommand', CopyLastCommandOutput = 'workbench.action.terminal.copyLastCommandOutput', CopyLastCommandAndLastCommandOutput = 'workbench.action.terminal.copyLastCommandAndLastCommandOutput', @@ -454,11 +455,9 @@ export const enum TerminalCommandId { ScrollDownLine = 'workbench.action.terminal.scrollDown', ScrollDownPage = 'workbench.action.terminal.scrollDownPage', ScrollToBottom = 'workbench.action.terminal.scrollToBottom', - ScrollToBottomAccessibleView = 'workbench.action.terminal.scrollToBottomAccessibleView', ScrollUpLine = 'workbench.action.terminal.scrollUp', ScrollUpPage = 'workbench.action.terminal.scrollUpPage', ScrollToTop = 'workbench.action.terminal.scrollToTop', - ScrollToTopAccessibleView = 'workbench.action.terminal.scrollToTopAccessibleView', Clear = 'workbench.action.terminal.clear', ClearSelection = 'workbench.action.terminal.clearSelection', ChangeIcon = 'workbench.action.terminal.changeIcon', @@ -577,7 +576,6 @@ export const DEFAULT_COMMANDS_TO_SKIP_SHELL: string[] = [ TerminalCommandId.AcceptSelectedSuggestion, TerminalCommandId.HideSuggestWidget, TerminalCommandId.FocusHover, - TerminalCommandId.FocusAccessibleBuffer, AccessibilityCommandId.OpenAccessibilityHelp, 'editor.action.toggleTabFocusMode', 'notifications.hideList', @@ -663,6 +661,7 @@ export const DEFAULT_COMMANDS_TO_SKIP_SHELL: string[] = [ 'workbench.action.terminal.chat.runCommand', 'workbench.action.terminal.chat.insertCommand', 'workbench.action.terminal.chat.viewInChat', + ...defaultTerminalAccessibilityCommandsToSkipShell ]; export const terminalContributionsDescriptor: IExtensionPointDescriptor = { diff --git a/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts b/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts index 1c44bfbeeef83..9f7b3295e11f6 100644 --- a/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts +++ b/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts @@ -16,6 +16,7 @@ import { Extensions as WorkbenchExtensions, IConfigurationMigrationRegistry, Con // Import configuration schemes from terminalContrib - this is an exception to the eslint rule since // they need to be declared at part of the rest of the terminal configuration +import { terminalAccessibilityConfiguration } from 'vs/workbench/contrib/terminalContrib/accessibility/common/terminalAccessibilityConfiguration'; // eslint-disable-line local/code-import-patterns import { terminalStickyScrollConfiguration } from 'vs/workbench/contrib/terminalContrib/stickyScroll/common/terminalStickyScrollConfiguration'; // eslint-disable-line local/code-import-patterns const terminalDescriptors = '\n- ' + [ @@ -664,16 +665,6 @@ const terminalConfiguration: IConfigurationNode = { localize('terminal.integrated.focusAfterRun.none', "Do nothing."), ] }, - [TerminalSettingId.AccessibleViewPreserveCursorPosition]: { - markdownDescription: localize('terminal.integrated.accessibleViewPreserveCursorPosition', "Preserve the cursor position on reopen of the terminal's accessible view rather than setting it to the bottom of the buffer."), - type: 'boolean', - default: false - }, - [TerminalSettingId.AccessibleViewFocusOnCommandExecution]: { - markdownDescription: localize('terminal.integrated.accessibleViewFocusOnCommandExecution', "Focus the terminal accessible view when a command is executed."), - type: 'boolean', - default: false - }, [TerminalSettingId.MouseWheelZoom]: { markdownDescription: isMacintosh ? localize('terminal.integrated.mouseWheelZoom.mac', "Zoom the font of the terminal when using mouse wheel and holding `Cmd`.") @@ -681,6 +672,7 @@ const terminalConfiguration: IConfigurationNode = { type: 'boolean', default: false }, + ...terminalAccessibilityConfiguration, ...terminalStickyScrollConfiguration } }; 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 2f231b15c43f8..6d814da682c37 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 @@ -19,7 +19,7 @@ import { ITerminalContribution, ITerminalInstance, ITerminalService, IXtermTermi import { registerTerminalAction } from 'vs/workbench/contrib/terminal/browser/terminalActions'; import { registerTerminalContribution } from 'vs/workbench/contrib/terminal/browser/terminalExtensions'; import { TerminalWidgetManager } from 'vs/workbench/contrib/terminal/browser/widgets/widgetManager'; -import { ITerminalProcessManager, TerminalCommandId } from 'vs/workbench/contrib/terminal/common/terminal'; +import { ITerminalProcessManager } from 'vs/workbench/contrib/terminal/common/terminal'; import { TerminalContextKeys } from 'vs/workbench/contrib/terminal/common/terminalContextKey'; import { BufferContentTracker } from 'vs/workbench/contrib/terminalContrib/accessibility/browser/bufferContentTracker'; import { TerminalAccessibilityHelpProvider } from 'vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibilityHelp'; @@ -33,6 +33,10 @@ import { Event } from 'vs/base/common/event'; import { ICurrentPartialCommand } from 'vs/platform/terminal/common/capabilities/commandDetection/terminalCommand'; import { AccessibilitySignal, IAccessibilitySignalService } from 'vs/platform/accessibilitySignal/browser/accessibilitySignalService'; import { alert } from 'vs/base/browser/ui/aria/aria'; +import { TerminalAccessibilitySettingId } from 'vs/workbench/contrib/terminalContrib/accessibility/common/terminalAccessibilityConfiguration'; +import { TerminalAccessibilityCommandId } from 'vs/workbench/contrib/terminalContrib/accessibility/common/terminal.accessibility'; + +// #region Contributions class TextAreaSyncContribution extends DisposableStore implements ITerminalContribution { static readonly ID = 'terminal.textAreaSync'; @@ -59,7 +63,6 @@ class TextAreaSyncContribution extends DisposableStore implements ITerminalContr } registerTerminalContribution(TextAreaSyncContribution.ID, TextAreaSyncContribution); - export class TerminalAccessibleViewContribution extends Disposable implements ITerminalContribution { static readonly ID = 'terminal.accessibleBufferProvider'; static get(instance: ITerminalInstance): TerminalAccessibleViewContribution | null { @@ -97,7 +100,7 @@ export class TerminalAccessibleViewContribution extends Disposable implements IT } })); this._register(this._configurationService.onDidChangeConfiguration(e => { - if (e.affectsConfiguration(TerminalSettingId.AccessibleViewFocusOnCommandExecution)) { + if (e.affectsConfiguration(TerminalAccessibilitySettingId.AccessibleViewFocusOnCommandExecution)) { this._updateCommandExecutedListener(); } })); @@ -137,7 +140,7 @@ export class TerminalAccessibleViewContribution extends Disposable implements IT if (!this._instance.capabilities.has(TerminalCapability.CommandDetection)) { return; } - if (!this._configurationService.getValue(TerminalSettingId.AccessibleViewFocusOnCommandExecution)) { + if (!this._configurationService.getValue(TerminalAccessibilitySettingId.AccessibleViewFocusOnCommandExecution)) { this._onDidRunCommand.clear(); return; } else if (this._onDidRunCommand.value) { @@ -168,7 +171,7 @@ export class TerminalAccessibleViewContribution extends Disposable implements IT return this._register(this._instantiationService.createInstance(TerminalAccessibilityHelpProvider, this._instance, this._xterm!)).provideContent(); })); } - const position = this._configurationService.getValue(TerminalSettingId.AccessibleViewPreserveCursorPosition) ? this._accessibleViewService.getPosition(AccessibleViewProviderId.Terminal) : undefined; + const position = this._configurationService.getValue(TerminalAccessibilitySettingId.AccessibleViewPreserveCursorPosition) ? this._accessibleViewService.getPosition(AccessibleViewProviderId.Terminal) : undefined; this._accessibleViewService.show(this._bufferProvider, position); } navigateToCommand(type: NavigationType): void { @@ -261,11 +264,14 @@ export class TerminalAccessibilityHelpContribution extends Disposable { } registerTerminalContribution(TerminalAccessibilityHelpContribution.ID, TerminalAccessibilityHelpContribution); +// #endregion + +// #region Actions class FocusAccessibleBufferAction extends Action2 { constructor() { super({ - id: TerminalCommandId.FocusAccessibleBuffer, + id: TerminalAccessibilityCommandId.FocusAccessibleBuffer, title: localize2('workbench.action.terminal.focusAccessibleBuffer', "Focus Accessible Terminal View"), precondition: ContextKeyExpr.or(TerminalContextKeys.processSupported, TerminalContextKeys.terminalHasBeenCreated), keybinding: [ @@ -294,7 +300,7 @@ class FocusAccessibleBufferAction extends Action2 { registerAction2(FocusAccessibleBufferAction); registerTerminalAction({ - id: TerminalCommandId.AccessibleBufferGoToNextCommand, + id: TerminalAccessibilityCommandId.AccessibleBufferGoToNextCommand, title: localize2('workbench.action.terminal.accessibleBufferGoToNextCommand', "Accessible Buffer Go to Next Command"), precondition: ContextKeyExpr.or(TerminalContextKeys.processSupported, TerminalContextKeys.terminalHasBeenCreated, ContextKeyExpr.and(accessibleViewIsShown, ContextKeyExpr.equals(accessibleViewCurrentProviderId.key, AccessibleViewProviderId.Terminal))), keybinding: [ @@ -313,9 +319,8 @@ registerTerminalAction({ } }); - registerTerminalAction({ - id: TerminalCommandId.AccessibleBufferGoToPreviousCommand, + id: TerminalAccessibilityCommandId.AccessibleBufferGoToPreviousCommand, title: localize2('workbench.action.terminal.accessibleBufferGoToPreviousCommand', "Accessible Buffer Go to Previous Command"), precondition: ContextKeyExpr.and(ContextKeyExpr.or(TerminalContextKeys.processSupported, TerminalContextKeys.terminalHasBeenCreated), ContextKeyExpr.and(accessibleViewIsShown, ContextKeyExpr.equals(accessibleViewCurrentProviderId.key, AccessibleViewProviderId.Terminal))), keybinding: [ @@ -335,7 +340,7 @@ registerTerminalAction({ }); registerTerminalAction({ - id: TerminalCommandId.ScrollToBottomAccessibleView, + id: TerminalAccessibilityCommandId.ScrollToBottomAccessibleView, title: localize2('workbench.action.terminal.scrollToBottomAccessibleView', 'Scroll to Accessible View Bottom'), precondition: ContextKeyExpr.and(ContextKeyExpr.or(TerminalContextKeys.processSupported, TerminalContextKeys.terminalHasBeenCreated), ContextKeyExpr.and(accessibleViewIsShown, ContextKeyExpr.equals(accessibleViewCurrentProviderId.key, AccessibleViewProviderId.Terminal))), keybinding: { @@ -355,7 +360,7 @@ registerTerminalAction({ }); registerTerminalAction({ - id: TerminalCommandId.ScrollToTopAccessibleView, + id: TerminalAccessibilityCommandId.ScrollToTopAccessibleView, title: localize2('workbench.action.terminal.scrollToTopAccessibleView', 'Scroll to Accessible View Top'), precondition: ContextKeyExpr.and(ContextKeyExpr.or(TerminalContextKeys.processSupported, TerminalContextKeys.terminalHasBeenCreated), ContextKeyExpr.and(accessibleViewIsShown, ContextKeyExpr.equals(accessibleViewCurrentProviderId.key, AccessibleViewProviderId.Terminal))), keybinding: { @@ -369,3 +374,5 @@ registerTerminalAction({ accessibleViewService.setPosition({ lineNumber: 1, column: 1 } as Position, true); } }); + +// #endregion diff --git a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibilityHelp.ts b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibilityHelp.ts index 4a3d33ff9ca91..0c2fac3401c92 100644 --- a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibilityHelp.ts +++ b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibilityHelp.ts @@ -19,6 +19,8 @@ import { ITerminalInstance, IXtermTerminal } from 'vs/workbench/contrib/terminal import { TerminalCommandId } from 'vs/workbench/contrib/terminal/common/terminal'; import type { Terminal } from '@xterm/xterm'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { TerminalAccessibilitySettingId } from 'vs/workbench/contrib/terminalContrib/accessibility/common/terminalAccessibilityConfiguration'; +import { TerminalAccessibilityCommandId } from 'vs/workbench/contrib/terminalContrib/accessibility/common/terminal.accessibility'; export const enum ClassName { Active = 'active', @@ -31,7 +33,7 @@ export class TerminalAccessibilityHelpProvider extends Disposable implements IAc onClose() { const expr = ContextKeyExpr.and(accessibleViewIsShown, ContextKeyExpr.equals(accessibleViewCurrentProviderId.key, AccessibleViewProviderId.TerminalHelp)); if (expr?.evaluate(this._contextKeyService.getContext(null))) { - this._commandService.executeCommand(TerminalCommandId.FocusAccessibleBuffer); + this._commandService.executeCommand(TerminalAccessibilityCommandId.FocusAccessibleBuffer); } else { this._instance.focus(); } @@ -77,9 +79,9 @@ export class TerminalAccessibilityHelpProvider extends Disposable implements IAc provideContent(): string { const content = []; - content.push(this._descriptionForCommand(TerminalCommandId.FocusAccessibleBuffer, localize('focusAccessibleTerminalView', 'The Focus Accessible Terminal View ({0}) command enables screen readers to read terminal contents.'), localize('focusAccessibleTerminalViewNoKb', 'The Focus Terminal Accessible View command enables screen readers to read terminal contents and is currently not triggerable by a keybinding.'))); + content.push(this._descriptionForCommand(TerminalAccessibilityCommandId.FocusAccessibleBuffer, localize('focusAccessibleTerminalView', 'The Focus Accessible Terminal View ({0}) command enables screen readers to read terminal contents.'), localize('focusAccessibleTerminalViewNoKb', 'The Focus Terminal Accessible View command enables screen readers to read terminal contents and is currently not triggerable by a keybinding.'))); content.push(localize('preserveCursor', 'Customize the behavior of the cursor when toggling between the terminal and accessible view with `terminal.integrated.accessibleViewPreserveCursorPosition.`')); - if (!this._configurationService.getValue(TerminalSettingId.AccessibleViewFocusOnCommandExecution)) { + if (!this._configurationService.getValue(TerminalAccessibilitySettingId.AccessibleViewFocusOnCommandExecution)) { content.push(localize('focusViewOnExecution', 'Enable `terminal.integrated.accessibleViewFocusOnCommandExecution` to automatically focus the terminal accessible view when a command is executed in the terminal.')); } if (this._instance.shellType === WindowsShellType.CommandPrompt) { @@ -88,8 +90,8 @@ export class TerminalAccessibilityHelpProvider extends Disposable implements IAc if (this._hasShellIntegration) { 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}) in the accessible view'), localize('goToNextCommandNoKb', 'Go to Next Command in the accessible view is currently not triggerable by a keybinding.'))); - shellIntegrationCommandList.push('- ' + this._descriptionForCommand(TerminalCommandId.AccessibleBufferGoToPreviousCommand, localize('goToPreviousCommand', 'Go to Previous Command ({0}) in the accessible view'), localize('goToPreviousCommandNoKb', 'Go to Previous Command in the accessible view is currently not triggerable by a keybinding.'))); + shellIntegrationCommandList.push('- ' + this._descriptionForCommand(TerminalAccessibilityCommandId.AccessibleBufferGoToNextCommand, localize('goToNextCommand', 'Go to Next Command ({0}) in the accessible view'), localize('goToNextCommandNoKb', 'Go to Next Command in the accessible view is currently not triggerable by a keybinding.'))); + shellIntegrationCommandList.push('- ' + this._descriptionForCommand(TerminalAccessibilityCommandId.AccessibleBufferGoToPreviousCommand, localize('goToPreviousCommand', 'Go to Previous Command ({0}) in the accessible view'), localize('goToPreviousCommandNoKb', 'Go to Previous Command in the accessible view is currently not triggerable by a keybinding.'))); shellIntegrationCommandList.push('- ' + this._descriptionForCommand(AccessibilityCommandId.GoToSymbol, localize('goToSymbol', 'Go to Symbol ({0})'), localize('goToSymbolNoKb', 'Go to symbol 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.'))); diff --git a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBufferProvider.ts b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBufferProvider.ts index 399e846921fe9..05a1f753a815a 100644 --- a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBufferProvider.ts +++ b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBufferProvider.ts @@ -10,11 +10,11 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { TerminalCapability, ITerminalCommand } from 'vs/platform/terminal/common/capabilities/capabilities'; import { ICurrentPartialCommand } from 'vs/platform/terminal/common/capabilities/commandDetection/terminalCommand'; -import { TerminalSettingId } from 'vs/platform/terminal/common/terminal'; import { AccessibilityVerbositySettingId, AccessibleViewProviderId } from 'vs/workbench/contrib/accessibility/browser/accessibilityConfiguration'; import { AccessibleViewType, IAccessibleViewContentProvider, IAccessibleViewOptions, IAccessibleViewSymbol } from 'vs/workbench/contrib/accessibility/browser/accessibleView'; import { ITerminalInstance, ITerminalService } from 'vs/workbench/contrib/terminal/browser/terminal'; import { BufferContentTracker } from 'vs/workbench/contrib/terminalContrib/accessibility/browser/bufferContentTracker'; +import { TerminalAccessibilitySettingId } from 'vs/workbench/contrib/terminalContrib/accessibility/common/terminalAccessibilityConfiguration'; export class TerminalAccessibleBufferProvider extends DisposableStore implements IAccessibleViewContentProvider { id = AccessibleViewProviderId.Terminal; @@ -34,11 +34,11 @@ export class TerminalAccessibleBufferProvider extends DisposableStore implements ) { super(); this.options.customHelp = customHelp; - this.options.position = configurationService.getValue(TerminalSettingId.AccessibleViewPreserveCursorPosition) ? 'initial-bottom' : 'bottom'; + this.options.position = configurationService.getValue(TerminalAccessibilitySettingId.AccessibleViewPreserveCursorPosition) ? 'initial-bottom' : 'bottom'; this.add(this._instance.onDisposed(() => this._onDidRequestClearProvider.fire(AccessibleViewProviderId.Terminal))); this.add(configurationService.onDidChangeConfiguration(e => { - if (e.affectsConfiguration(TerminalSettingId.AccessibleViewPreserveCursorPosition)) { - this.options.position = configurationService.getValue(TerminalSettingId.AccessibleViewPreserveCursorPosition) ? 'initial-bottom' : 'bottom'; + if (e.affectsConfiguration(TerminalAccessibilitySettingId.AccessibleViewPreserveCursorPosition)) { + this.options.position = configurationService.getValue(TerminalAccessibilitySettingId.AccessibleViewPreserveCursorPosition) ? 'initial-bottom' : 'bottom'; } })); this._focusedInstance = _terminalService.activeInstance; diff --git a/src/vs/workbench/contrib/terminalContrib/accessibility/common/terminal.accessibility.ts b/src/vs/workbench/contrib/terminalContrib/accessibility/common/terminal.accessibility.ts new file mode 100644 index 0000000000000..492b11f19ab99 --- /dev/null +++ b/src/vs/workbench/contrib/terminalContrib/accessibility/common/terminal.accessibility.ts @@ -0,0 +1,16 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +export const enum TerminalAccessibilityCommandId { + FocusAccessibleBuffer = 'workbench.action.terminal.focusAccessibleBuffer', + AccessibleBufferGoToNextCommand = 'workbench.action.terminal.accessibleBufferGoToNextCommand', + AccessibleBufferGoToPreviousCommand = 'workbench.action.terminal.accessibleBufferGoToPreviousCommand', + ScrollToBottomAccessibleView = 'workbench.action.terminal.scrollToBottomAccessibleView', + ScrollToTopAccessibleView = 'workbench.action.terminal.scrollToTopAccessibleView', +} + +export const defaultTerminalAccessibilityCommandsToSkipShell = [ + TerminalAccessibilityCommandId.FocusAccessibleBuffer +]; diff --git a/src/vs/workbench/contrib/terminalContrib/accessibility/common/terminalAccessibilityConfiguration.ts b/src/vs/workbench/contrib/terminalContrib/accessibility/common/terminalAccessibilityConfiguration.ts new file mode 100644 index 0000000000000..29d5be506d501 --- /dev/null +++ b/src/vs/workbench/contrib/terminalContrib/accessibility/common/terminalAccessibilityConfiguration.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 type { IStringDictionary } from 'vs/base/common/collections'; +import { localize } from 'vs/nls'; +import type { IConfigurationPropertySchema } from 'vs/platform/configuration/common/configurationRegistry'; + +export const enum TerminalAccessibilitySettingId { + AccessibleViewPreserveCursorPosition = 'terminal.integrated.accessibleViewPreserveCursorPosition', + AccessibleViewFocusOnCommandExecution = 'terminal.integrated.accessibleViewFocusOnCommandExecution', +} + +export interface ITerminalAccessibilityConfiguration { + accessibleViewPreserveCursorPosition: boolean; + accessibleViewFocusOnCommandExecution: number; +} + +export const terminalAccessibilityConfiguration: IStringDictionary = { + [TerminalAccessibilitySettingId.AccessibleViewPreserveCursorPosition]: { + markdownDescription: localize('terminal.integrated.accessibleViewPreserveCursorPosition', "Preserve the cursor position on reopen of the terminal's accessible view rather than setting it to the bottom of the buffer."), + type: 'boolean', + default: false + }, + [TerminalAccessibilitySettingId.AccessibleViewFocusOnCommandExecution]: { + markdownDescription: localize('terminal.integrated.accessibleViewFocusOnCommandExecution', "Focus the terminal accessible view when a command is executed."), + type: 'boolean', + default: false + }, +}; From f58f52517493cf4eb55140750096721867a8a1d8 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Sun, 28 Apr 2024 06:01:47 -0700 Subject: [PATCH 062/104] More more terminal chat code into terminalContrib --- .../terminal.accessibility.contribution.ts | 2 +- .../chat/browser/terminal.chat.contribution.ts | 16 ++++++++++++++-- .../terminal.stickyScroll.contribution.ts | 2 +- 3 files changed, 16 insertions(+), 4 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 6d814da682c37..a77db21d05444 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 @@ -36,7 +36,7 @@ import { alert } from 'vs/base/browser/ui/aria/aria'; import { TerminalAccessibilitySettingId } from 'vs/workbench/contrib/terminalContrib/accessibility/common/terminalAccessibilityConfiguration'; import { TerminalAccessibilityCommandId } from 'vs/workbench/contrib/terminalContrib/accessibility/common/terminal.accessibility'; -// #region Contributions +// #region Terminal Contributions class TextAreaSyncContribution extends DisposableStore implements ITerminalContribution { static readonly ID = 'terminal.textAreaSync'; diff --git a/src/vs/workbench/contrib/terminalContrib/chat/browser/terminal.chat.contribution.ts b/src/vs/workbench/contrib/terminalContrib/chat/browser/terminal.chat.contribution.ts index 44eabbf13f6b1..14a3330d3f0e8 100644 --- a/src/vs/workbench/contrib/terminalContrib/chat/browser/terminal.chat.contribution.ts +++ b/src/vs/workbench/contrib/terminalContrib/chat/browser/terminal.chat.contribution.ts @@ -7,11 +7,23 @@ import { WorkbenchPhase, registerWorkbenchContribution2 } from 'vs/workbench/com import { registerTerminalContribution } from 'vs/workbench/contrib/terminal/browser/terminalExtensions'; import { TerminalInlineChatAccessibleViewContribution } from 'vs/workbench/contrib/terminalContrib/chat/browser/terminalChatAccessibleView'; import { TerminalChatController } from 'vs/workbench/contrib/terminalContrib/chat/browser/terminalChatController'; - -import 'vs/workbench/contrib/terminalContrib/chat/browser/terminalChatActions'; import { TerminalChatAccessibilityHelpContribution } from 'vs/workbench/contrib/terminalContrib/chat/browser/terminalChatAccessibilityHelp'; +// #region Terminal Contributions + registerTerminalContribution(TerminalChatController.ID, TerminalChatController, false); +// #endregion + +// #region Contributions + registerWorkbenchContribution2(TerminalInlineChatAccessibleViewContribution.ID, TerminalInlineChatAccessibleViewContribution, WorkbenchPhase.Eventually); registerWorkbenchContribution2(TerminalChatAccessibilityHelpContribution.ID, TerminalChatAccessibilityHelpContribution, WorkbenchPhase.Eventually); + +// #endregion + +// #region Actions + +import 'vs/workbench/contrib/terminalContrib/chat/browser/terminalChatActions'; + +// #endregion diff --git a/src/vs/workbench/contrib/terminalContrib/stickyScroll/browser/terminal.stickyScroll.contribution.ts b/src/vs/workbench/contrib/terminalContrib/stickyScroll/browser/terminal.stickyScroll.contribution.ts index cfac60baf6379..6f6b7193334f1 100644 --- a/src/vs/workbench/contrib/terminalContrib/stickyScroll/browser/terminal.stickyScroll.contribution.ts +++ b/src/vs/workbench/contrib/terminalContrib/stickyScroll/browser/terminal.stickyScroll.contribution.ts @@ -13,7 +13,7 @@ import { registerTerminalContribution } from 'vs/workbench/contrib/terminal/brow import { TerminalStickyScrollContribution } from 'vs/workbench/contrib/terminalContrib/stickyScroll/browser/terminalStickyScrollContribution'; import { TerminalStickyScrollSettingId } from 'vs/workbench/contrib/terminalContrib/stickyScroll/common/terminalStickyScrollConfiguration'; -// #region Contributions +// #region Terminal Contributions registerTerminalContribution(TerminalStickyScrollContribution.ID, TerminalStickyScrollContribution, true); From 77dae82cb65d60acc62cc6473fe4268aa5da799b Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Sun, 28 Apr 2024 06:05:26 -0700 Subject: [PATCH 063/104] More more terminal developer code into terminalContrib --- .../contrib/terminal/browser/baseTerminalBackend.ts | 7 +++++-- src/vs/workbench/contrib/terminal/common/terminal.ts | 8 +------- .../browser/terminal.developer.contribution.ts | 9 +++++---- .../developer/common/terminal.developer.ts | 10 ++++++++++ 4 files changed, 21 insertions(+), 13 deletions(-) create mode 100644 src/vs/workbench/contrib/terminalContrib/developer/common/terminal.developer.ts diff --git a/src/vs/workbench/contrib/terminal/browser/baseTerminalBackend.ts b/src/vs/workbench/contrib/terminal/browser/baseTerminalBackend.ts index 12b5058d65a98..d375636a4c949 100644 --- a/src/vs/workbench/contrib/terminal/browser/baseTerminalBackend.ts +++ b/src/vs/workbench/contrib/terminal/browser/baseTerminalBackend.ts @@ -9,11 +9,14 @@ import { Schemas } from 'vs/base/common/network'; import { localize } from 'vs/nls'; import { ICrossVersionSerializedTerminalState, IPtyHostController, ISerializedTerminalState, ITerminalLogService } from 'vs/platform/terminal/common/terminal'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; -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'; import { IStatusbarEntry, IStatusbarEntryAccessor, IStatusbarService, StatusbarAlignment } from 'vs/workbench/services/statusbar/browser/statusbar'; +// HACK: This file should not depend on terminalContrib +// eslint-disable-next-line local/code-import-patterns +import { TerminalDeveloperCommandId } from 'vs/workbench/contrib/terminalContrib/developer/common/terminal.developer'; + export abstract class BaseTerminalBackend extends Disposable { private _isPtyHostUnresponsive: boolean = false; @@ -65,7 +68,7 @@ export abstract class BaseTerminalBackend extends Disposable { text: `$(debug-disconnect) ${localize('ptyHostStatus.short', 'Pty Host')}`, 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, + command: TerminalDeveloperCommandId.RestartPtyHost, kind: 'warning' }; } diff --git a/src/vs/workbench/contrib/terminal/common/terminal.ts b/src/vs/workbench/contrib/terminal/common/terminal.ts index 8583343525903..7f462316719e5 100644 --- a/src/vs/workbench/contrib/terminal/common/terminal.ts +++ b/src/vs/workbench/contrib/terminal/common/terminal.ts @@ -21,7 +21,7 @@ import { IExtensionPointDescriptor } from 'vs/workbench/services/extensions/comm // Import commands to skip shell from terminalContrib - this is an exception to the eslint rule // since they need to be included in the terminal module -import { defaultTerminalAccessibilityCommandsToSkipShell } from 'vs/workbench/contrib/terminalContrib/accessibility/browser/terminal.accessibility'; // eslint-disable-line local/code-import-patterns +import { defaultTerminalAccessibilityCommandsToSkipShell } from 'vs/workbench/contrib/terminalContrib/accessibility/common/terminal.accessibility'; // eslint-disable-line local/code-import-patterns export const TERMINAL_VIEW_ID = 'terminal'; @@ -501,12 +501,6 @@ export const enum TerminalCommandId { FontZoomIn = 'workbench.action.terminal.fontZoomIn', FontZoomOut = 'workbench.action.terminal.fontZoomOut', FontZoomReset = 'workbench.action.terminal.fontZoomReset', - - // Developer commands - - WriteDataToTerminal = 'workbench.action.terminal.writeDataToTerminal', - ShowTextureAtlas = 'workbench.action.terminal.showTextureAtlas', - RestartPtyHost = 'workbench.action.terminal.restartPtyHost', } export const DEFAULT_COMMANDS_TO_SKIP_SHELL: string[] = [ diff --git a/src/vs/workbench/contrib/terminalContrib/developer/browser/terminal.developer.contribution.ts b/src/vs/workbench/contrib/terminalContrib/developer/browser/terminal.developer.contribution.ts index 692c2588c4a0a..3ac4007888441 100644 --- a/src/vs/workbench/contrib/terminalContrib/developer/browser/terminal.developer.contribution.ts +++ b/src/vs/workbench/contrib/terminalContrib/developer/browser/terminal.developer.contribution.ts @@ -20,14 +20,15 @@ import { IInternalXtermTerminal, ITerminalContribution, ITerminalInstance, IXter import { registerTerminalAction } from 'vs/workbench/contrib/terminal/browser/terminalActions'; import { registerTerminalContribution } from 'vs/workbench/contrib/terminal/browser/terminalExtensions'; import { TerminalWidgetManager } from 'vs/workbench/contrib/terminal/browser/widgets/widgetManager'; -import { ITerminalProcessManager, TerminalCommandId } from 'vs/workbench/contrib/terminal/common/terminal'; +import { ITerminalProcessManager } from 'vs/workbench/contrib/terminal/common/terminal'; import { TerminalContextKeys } from 'vs/workbench/contrib/terminal/common/terminalContextKey'; import type { Terminal } from '@xterm/xterm'; import { ITerminalCommand, TerminalCapability, type ICommandDetectionCapability } from 'vs/platform/terminal/common/capabilities/capabilities'; import { IStatusbarService, StatusbarAlignment, type IStatusbarEntry, type IStatusbarEntryAccessor } from 'vs/workbench/services/statusbar/browser/statusbar'; +import { TerminalDeveloperCommandId } from 'vs/workbench/contrib/terminalContrib/developer/common/terminal.developer'; registerTerminalAction({ - id: TerminalCommandId.ShowTextureAtlas, + id: TerminalDeveloperCommandId.ShowTextureAtlas, title: localize2('workbench.action.terminal.showTextureAtlas', 'Show Terminal Texture Atlas'), category: Categories.Developer, precondition: ContextKeyExpr.or(TerminalContextKeys.isOpen), @@ -59,7 +60,7 @@ registerTerminalAction({ }); registerTerminalAction({ - id: TerminalCommandId.WriteDataToTerminal, + id: TerminalDeveloperCommandId.WriteDataToTerminal, title: localize2('workbench.action.terminal.writeDataToTerminal', 'Write Data to Terminal'), category: Categories.Developer, run: async (c, accessor) => { @@ -95,7 +96,7 @@ registerTerminalAction({ registerTerminalAction({ - id: TerminalCommandId.RestartPtyHost, + id: TerminalDeveloperCommandId.RestartPtyHost, title: localize2('workbench.action.terminal.restartPtyHost', 'Restart Pty Host'), category: Categories.Developer, run: async (c, accessor) => { diff --git a/src/vs/workbench/contrib/terminalContrib/developer/common/terminal.developer.ts b/src/vs/workbench/contrib/terminalContrib/developer/common/terminal.developer.ts new file mode 100644 index 0000000000000..39d0f040af1ce --- /dev/null +++ b/src/vs/workbench/contrib/terminalContrib/developer/common/terminal.developer.ts @@ -0,0 +1,10 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +export const enum TerminalDeveloperCommandId { + WriteDataToTerminal = 'workbench.action.terminal.writeDataToTerminal', + ShowTextureAtlas = 'workbench.action.terminal.showTextureAtlas', + RestartPtyHost = 'workbench.action.terminal.restartPtyHost', +} From f97aef4bca27a7129bcc6781d68ca04ed483ef42 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Sun, 28 Apr 2024 06:13:11 -0700 Subject: [PATCH 064/104] More more terminal env/find code into terminalContrib --- .../terminal/browser/media/terminal.css | 16 ----------- .../contrib/terminal/common/terminal.ts | 19 ++----------- ...erminal.environmentChanges.contribution.ts | 3 ++ .../find/browser/media/terminalFind.css | 21 ++++++++++++++ .../browser/terminal.find.contribution.ts | 28 +++++++++++++------ .../find/browser/terminalFindWidget.ts | 14 +++++----- .../find/common/terminal.find.ts | 26 +++++++++++++++++ 7 files changed, 79 insertions(+), 48 deletions(-) create mode 100644 src/vs/workbench/contrib/terminalContrib/find/browser/media/terminalFind.css create mode 100644 src/vs/workbench/contrib/terminalContrib/find/common/terminal.find.ts diff --git a/src/vs/workbench/contrib/terminal/browser/media/terminal.css b/src/vs/workbench/contrib/terminal/browser/media/terminal.css index e28872179e047..c3ee3fb42d7ef 100644 --- a/src/vs/workbench/contrib/terminal/browser/media/terminal.css +++ b/src/vs/workbench/contrib/terminal/browser/media/terminal.css @@ -513,22 +513,6 @@ .terminal-scroll-highlight.terminal-scroll-highlight-outline { border-color: var(--vscode-focusBorder); } -.hc-black .xterm-find-result-decoration, -.hc-light .xterm-find-result-decoration { - outline-style: dotted !important; -} - -.hc-black .xterm-find-result-decoration, -.hc-light .xterm-find-result-decoration { - outline-style: solid !important; -} - -.xterm-find-active-result-decoration { - outline-style: solid !important; - outline-width: 2px !important; - /* Ensure the active decoration is above the regular decoration */ - z-index: 7 !important; -} .monaco-workbench.hc-black .editor-instance .xterm.focus::before, .monaco-workbench.hc-black .pane-body.integrated-terminal .xterm.focus::before, diff --git a/src/vs/workbench/contrib/terminal/common/terminal.ts b/src/vs/workbench/contrib/terminal/common/terminal.ts index 7f462316719e5..5f0c60eb3cc4e 100644 --- a/src/vs/workbench/contrib/terminal/common/terminal.ts +++ b/src/vs/workbench/contrib/terminal/common/terminal.ts @@ -22,6 +22,7 @@ import { IExtensionPointDescriptor } from 'vs/workbench/services/extensions/comm // Import commands to skip shell from terminalContrib - this is an exception to the eslint rule // since they need to be included in the terminal module import { defaultTerminalAccessibilityCommandsToSkipShell } from 'vs/workbench/contrib/terminalContrib/accessibility/common/terminal.accessibility'; // eslint-disable-line local/code-import-patterns +import { defaultTerminalFindCommandToSkipShell } from 'vs/workbench/contrib/terminalContrib/find/common/terminal.find'; // eslint-disable-line local/code-import-patterns export const TERMINAL_VIEW_ID = 'terminal'; @@ -390,8 +391,6 @@ export interface ISerializedTerminalInstanceContext { export const QUICK_LAUNCH_PROFILE_CHOICE = 'workbench.action.terminal.profile.choice'; export const enum TerminalCommandId { - FindNext = 'workbench.action.terminal.findNext', - FindPrevious = 'workbench.action.terminal.findPrevious', Toggle = 'workbench.action.terminal.toggleTerminal', Kill = 'workbench.action.terminal.kill', KillViewOrEditor = 'workbench.action.terminal.killViewOrEditor', @@ -467,8 +466,6 @@ export const enum TerminalCommandId { Rename = 'workbench.action.terminal.rename', RenameActiveTab = 'workbench.action.terminal.renameActiveTab', RenameWithArgs = 'workbench.action.terminal.renameWithArg', - FindFocus = 'workbench.action.terminal.focusFind', - FindHide = 'workbench.action.terminal.hideFind', QuickOpenTerm = 'workbench.action.quickOpenTerm', ScrollToPreviousCommand = 'workbench.action.terminal.scrollToPreviousCommand', ScrollToNextCommand = 'workbench.action.terminal.scrollToNextCommand', @@ -477,10 +474,6 @@ export const enum TerminalCommandId { SelectToPreviousLine = 'workbench.action.terminal.selectToPreviousLine', SelectToNextLine = 'workbench.action.terminal.selectToNextLine', SendSequence = 'workbench.action.terminal.sendSequence', - ToggleFindRegex = 'workbench.action.terminal.toggleFindRegex', - ToggleFindWholeWord = 'workbench.action.terminal.toggleFindWholeWord', - ToggleFindCaseSensitive = 'workbench.action.terminal.toggleFindCaseSensitive', - SearchWorkspace = 'workbench.action.terminal.searchWorkspace', AttachToSession = 'workbench.action.terminal.attachToSession', DetachSession = 'workbench.action.terminal.detachSession', MoveToEditor = 'workbench.action.terminal.moveToEditor', @@ -515,14 +508,7 @@ export const DEFAULT_COMMANDS_TO_SKIP_SHELL: string[] = [ TerminalCommandId.DeleteToLineStart, TerminalCommandId.DeleteWordLeft, TerminalCommandId.DeleteWordRight, - TerminalCommandId.FindFocus, - TerminalCommandId.FindHide, - TerminalCommandId.FindNext, - TerminalCommandId.FindPrevious, TerminalCommandId.GoToRecentDirectory, - TerminalCommandId.ToggleFindRegex, - TerminalCommandId.ToggleFindWholeWord, - TerminalCommandId.ToggleFindCaseSensitive, TerminalCommandId.FocusNextPane, TerminalCommandId.FocusNext, TerminalCommandId.FocusPreviousPane, @@ -655,7 +641,8 @@ export const DEFAULT_COMMANDS_TO_SKIP_SHELL: string[] = [ 'workbench.action.terminal.chat.runCommand', 'workbench.action.terminal.chat.insertCommand', 'workbench.action.terminal.chat.viewInChat', - ...defaultTerminalAccessibilityCommandsToSkipShell + ...defaultTerminalAccessibilityCommandsToSkipShell, + ...defaultTerminalFindCommandToSkipShell, ]; export const terminalContributionsDescriptor: IExtensionPointDescriptor = { 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 e12eb04ebd5b0..faf67e936151b 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 @@ -17,6 +17,8 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic // TODO: The rest of the terminal environment changes feature should move here /~https://github.com/microsoft/vscode/issues/177241 +// #region Actions + registerActiveInstanceAction({ id: TerminalCommandId.ShowEnvironmentContributions, title: localize2('workbench.action.terminal.showEnvironmentContributions', 'Show Environment Contributions'), @@ -45,6 +47,7 @@ registerActiveInstanceAction({ } }); +// #endregion function describeEnvironmentChanges(collection: IMergedEnvironmentVariableCollection, scope: EnvironmentVariableScope | undefined): string { let content = `# ${localize('envChanges', 'Terminal Environment Changes')}`; diff --git a/src/vs/workbench/contrib/terminalContrib/find/browser/media/terminalFind.css b/src/vs/workbench/contrib/terminalContrib/find/browser/media/terminalFind.css new file mode 100644 index 0000000000000..544d4e639f8ff --- /dev/null +++ b/src/vs/workbench/contrib/terminalContrib/find/browser/media/terminalFind.css @@ -0,0 +1,21 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +.hc-black .xterm-find-result-decoration, +.hc-light .xterm-find-result-decoration { + outline-style: dotted !important; +} + +.hc-black .xterm-find-result-decoration, +.hc-light .xterm-find-result-decoration { + outline-style: solid !important; +} + +.xterm-find-active-result-decoration { + outline-style: solid !important; + outline-width: 2px !important; + /* Ensure the active decoration is above the regular decoration */ + z-index: 7 !important; +} diff --git a/src/vs/workbench/contrib/terminalContrib/find/browser/terminal.find.contribution.ts b/src/vs/workbench/contrib/terminalContrib/find/browser/terminal.find.contribution.ts index 5556b7e5d7f4c..c93f1236a78c5 100644 --- a/src/vs/workbench/contrib/terminalContrib/find/browser/terminal.find.contribution.ts +++ b/src/vs/workbench/contrib/terminalContrib/find/browser/terminal.find.contribution.ts @@ -16,10 +16,14 @@ import { IDetachedTerminalInstance, ITerminalContribution, ITerminalInstance, IT import { registerActiveInstanceAction, registerActiveXtermAction } from 'vs/workbench/contrib/terminal/browser/terminalActions'; import { registerTerminalContribution } from 'vs/workbench/contrib/terminal/browser/terminalExtensions'; import { TerminalWidgetManager } from 'vs/workbench/contrib/terminal/browser/widgets/widgetManager'; -import { ITerminalProcessInfo, ITerminalProcessManager, TerminalCommandId } from 'vs/workbench/contrib/terminal/common/terminal'; +import { ITerminalProcessInfo, ITerminalProcessManager } from 'vs/workbench/contrib/terminal/common/terminal'; import { TerminalContextKeys } from 'vs/workbench/contrib/terminal/common/terminalContextKey'; import { TerminalFindWidget } from 'vs/workbench/contrib/terminalContrib/find/browser/terminalFindWidget'; import type { Terminal as RawXtermTerminal } from '@xterm/xterm'; +import { TerminalFindCommandId } from 'vs/workbench/contrib/terminalContrib/find/common/terminal.find'; +import 'vs/css!./media/terminalFind'; + +// #region Terminal Contributions class TerminalFindContribution extends Disposable implements ITerminalContribution { static readonly ID = 'terminal.find'; @@ -97,8 +101,12 @@ class TerminalFindContribution extends Disposable implements ITerminalContributi } registerTerminalContribution(TerminalFindContribution.ID, TerminalFindContribution, true); +// #endregion + +// #region Actions + registerActiveXtermAction({ - id: TerminalCommandId.FindFocus, + id: TerminalFindCommandId.FindFocus, title: localize2('workbench.action.terminal.focusFind', 'Focus Find'), keybinding: { primary: KeyMod.CtrlCmd | KeyCode.KeyF, @@ -113,7 +121,7 @@ registerActiveXtermAction({ }); registerActiveXtermAction({ - id: TerminalCommandId.FindHide, + id: TerminalFindCommandId.FindHide, title: localize2('workbench.action.terminal.hideFind', 'Hide Find'), keybinding: { primary: KeyCode.Escape, @@ -129,7 +137,7 @@ registerActiveXtermAction({ }); registerActiveXtermAction({ - id: TerminalCommandId.ToggleFindRegex, + id: TerminalFindCommandId.ToggleFindRegex, title: localize2('workbench.action.terminal.toggleFindRegex', 'Toggle Find Using Regex'), keybinding: { primary: KeyMod.Alt | KeyCode.KeyR, @@ -146,7 +154,7 @@ registerActiveXtermAction({ }); registerActiveXtermAction({ - id: TerminalCommandId.ToggleFindWholeWord, + id: TerminalFindCommandId.ToggleFindWholeWord, title: localize2('workbench.action.terminal.toggleFindWholeWord', 'Toggle Find Using Whole Word'), keybinding: { primary: KeyMod.Alt | KeyCode.KeyW, @@ -163,7 +171,7 @@ registerActiveXtermAction({ }); registerActiveXtermAction({ - id: TerminalCommandId.ToggleFindCaseSensitive, + id: TerminalFindCommandId.ToggleFindCaseSensitive, title: localize2('workbench.action.terminal.toggleFindCaseSensitive', 'Toggle Find Using Case Sensitive'), keybinding: { primary: KeyMod.Alt | KeyCode.KeyC, @@ -180,7 +188,7 @@ registerActiveXtermAction({ }); registerActiveXtermAction({ - id: TerminalCommandId.FindNext, + id: TerminalFindCommandId.FindNext, title: localize2('workbench.action.terminal.findNext', 'Find Next'), keybinding: [ { @@ -207,7 +215,7 @@ registerActiveXtermAction({ }); registerActiveXtermAction({ - id: TerminalCommandId.FindPrevious, + id: TerminalFindCommandId.FindPrevious, title: localize2('workbench.action.terminal.findPrevious', 'Find Previous'), keybinding: [ { @@ -235,7 +243,7 @@ registerActiveXtermAction({ // Global workspace file search registerActiveInstanceAction({ - id: TerminalCommandId.SearchWorkspace, + id: TerminalFindCommandId.SearchWorkspace, title: localize2('workbench.action.terminal.searchWorkspace', 'Search Workspace'), keybinding: [ { @@ -246,3 +254,5 @@ registerActiveInstanceAction({ ], run: (activeInstance, c, accessor) => findInFilesCommand(accessor, { query: activeInstance.selection }) }); + +// #endregion diff --git a/src/vs/workbench/contrib/terminalContrib/find/browser/terminalFindWidget.ts b/src/vs/workbench/contrib/terminalContrib/find/browser/terminalFindWidget.ts index eee6410fd9b01..eec3455a76584 100644 --- a/src/vs/workbench/contrib/terminalContrib/find/browser/terminalFindWidget.ts +++ b/src/vs/workbench/contrib/terminalContrib/find/browser/terminalFindWidget.ts @@ -14,11 +14,11 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { Event } from 'vs/base/common/event'; import type { ISearchOptions } from '@xterm/addon-search'; -import { TerminalCommandId } from 'vs/workbench/contrib/terminal/common/terminal'; import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; import { openContextMenu } from 'vs/workbench/contrib/terminalContrib/find/browser/textInputContextMenu'; import { IDisposable } from 'vs/base/common/lifecycle'; import { IHoverService } from 'vs/platform/hover/browser/hover'; +import { TerminalFindCommandId } from 'vs/workbench/contrib/terminalContrib/find/common/terminal.find'; const TERMINAL_FIND_WIDGET_INITIAL_WIDTH = 419; @@ -46,12 +46,12 @@ export class TerminalFindWidget extends SimpleFindWidget { showResultCount: true, initialWidth: TERMINAL_FIND_WIDGET_INITIAL_WIDTH, enableSash: true, - appendCaseSensitiveActionId: TerminalCommandId.ToggleFindCaseSensitive, - appendRegexActionId: TerminalCommandId.ToggleFindRegex, - appendWholeWordsActionId: TerminalCommandId.ToggleFindWholeWord, - previousMatchActionId: TerminalCommandId.FindPrevious, - nextMatchActionId: TerminalCommandId.FindNext, - closeWidgetActionId: TerminalCommandId.FindHide, + appendCaseSensitiveActionId: TerminalFindCommandId.ToggleFindCaseSensitive, + appendRegexActionId: TerminalFindCommandId.ToggleFindRegex, + appendWholeWordsActionId: TerminalFindCommandId.ToggleFindWholeWord, + previousMatchActionId: TerminalFindCommandId.FindPrevious, + nextMatchActionId: TerminalFindCommandId.FindNext, + closeWidgetActionId: TerminalFindCommandId.FindHide, type: 'Terminal', matchesLimit: XtermTerminalConstants.SearchHighlightLimit }, _contextViewService, _contextKeyService, hoverService, keybindingService); diff --git a/src/vs/workbench/contrib/terminalContrib/find/common/terminal.find.ts b/src/vs/workbench/contrib/terminalContrib/find/common/terminal.find.ts new file mode 100644 index 0000000000000..99d0cdf130a79 --- /dev/null +++ b/src/vs/workbench/contrib/terminalContrib/find/common/terminal.find.ts @@ -0,0 +1,26 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +export const enum TerminalFindCommandId { + FindFocus = 'workbench.action.terminal.focusFind', + FindHide = 'workbench.action.terminal.hideFind', + FindNext = 'workbench.action.terminal.findNext', + FindPrevious = 'workbench.action.terminal.findPrevious', + ToggleFindRegex = 'workbench.action.terminal.toggleFindRegex', + ToggleFindWholeWord = 'workbench.action.terminal.toggleFindWholeWord', + ToggleFindCaseSensitive = 'workbench.action.terminal.toggleFindCaseSensitive', + SearchWorkspace = 'workbench.action.terminal.searchWorkspace', +} + +export const defaultTerminalFindCommandToSkipShell = [ + TerminalFindCommandId.FindFocus, + TerminalFindCommandId.FindHide, + TerminalFindCommandId.FindNext, + TerminalFindCommandId.FindPrevious, + TerminalFindCommandId.ToggleFindRegex, + TerminalFindCommandId.ToggleFindWholeWord, + TerminalFindCommandId.ToggleFindCaseSensitive, + TerminalFindCommandId.SearchWorkspace, +]; From ea7c90c9f4badb1754d5a25378b6aecd99672d47 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Sun, 28 Apr 2024 06:17:09 -0700 Subject: [PATCH 065/104] More more terminal highlight/links code into terminalContrib --- .../contrib/terminal/common/terminal.ts | 4 ---- .../browser/terminalAccessibilityHelp.ts | 3 ++- .../terminal.highlight.contribution.ts | 4 +++- .../browser/terminal.links.contribution.ts | 21 +++++++++++++++---- .../links/common/terminal.links.ts | 11 ++++++++++ 5 files changed, 33 insertions(+), 10 deletions(-) create mode 100644 src/vs/workbench/contrib/terminalContrib/links/common/terminal.links.ts diff --git a/src/vs/workbench/contrib/terminal/common/terminal.ts b/src/vs/workbench/contrib/terminal/common/terminal.ts index 5f0c60eb3cc4e..9ba0b3a2d562e 100644 --- a/src/vs/workbench/contrib/terminal/common/terminal.ts +++ b/src/vs/workbench/contrib/terminal/common/terminal.ts @@ -399,11 +399,7 @@ export const enum TerminalCommandId { KillAll = 'workbench.action.terminal.killAll', QuickKill = 'workbench.action.terminal.quickKill', ConfigureTerminalSettings = 'workbench.action.terminal.openSettings', - OpenDetectedLink = 'workbench.action.terminal.openDetectedLink', - OpenWordLink = 'workbench.action.terminal.openWordLink', ShellIntegrationLearnMore = 'workbench.action.terminal.learnMore', - OpenFileLink = 'workbench.action.terminal.openFileLink', - OpenWebLink = 'workbench.action.terminal.openUrlLink', RunRecentCommand = 'workbench.action.terminal.runRecentCommand', CopyLastCommand = 'workbench.action.terminal.copyLastCommand', CopyLastCommandOutput = 'workbench.action.terminal.copyLastCommandOutput', diff --git a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibilityHelp.ts b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibilityHelp.ts index 0c2fac3401c92..ad967c57b5aa1 100644 --- a/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibilityHelp.ts +++ b/src/vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibilityHelp.ts @@ -21,6 +21,7 @@ import type { Terminal } from '@xterm/xterm'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { TerminalAccessibilitySettingId } from 'vs/workbench/contrib/terminalContrib/accessibility/common/terminalAccessibilityConfiguration'; import { TerminalAccessibilityCommandId } from 'vs/workbench/contrib/terminalContrib/accessibility/common/terminal.accessibility'; +import { TerminalLinksCommandId } from 'vs/workbench/contrib/terminalContrib/links/common/terminal.links'; export const enum ClassName { Active = 'active', @@ -99,7 +100,7 @@ export class TerminalAccessibilityHelpProvider extends Disposable implements IAc } 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(TerminalLinksCommandId.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('focusAfterRun', 'Configure what gets focused after running selected text in the terminal with `{0}`.', TerminalSettingId.FocusAfterRun)); return content.join('\n\n'); diff --git a/src/vs/workbench/contrib/terminalContrib/highlight/browser/terminal.highlight.contribution.ts b/src/vs/workbench/contrib/terminalContrib/highlight/browser/terminal.highlight.contribution.ts index d2dde144b7609..2217fb1aed13b 100644 --- a/src/vs/workbench/contrib/terminalContrib/highlight/browser/terminal.highlight.contribution.ts +++ b/src/vs/workbench/contrib/terminalContrib/highlight/browser/terminal.highlight.contribution.ts @@ -12,7 +12,7 @@ import { registerTerminalContribution } from 'vs/workbench/contrib/terminal/brow import { TerminalWidgetManager } from 'vs/workbench/contrib/terminal/browser/widgets/widgetManager'; import { ITerminalProcessInfo, ITerminalProcessManager } from 'vs/workbench/contrib/terminal/common/terminal'; - +// #region Terminal Contributions class TerminalHighlightContribution extends Disposable implements ITerminalContribution { static readonly ID = 'terminal.highlight'; @@ -55,3 +55,5 @@ class TerminalHighlightContribution extends Disposable implements ITerminalContr } registerTerminalContribution(TerminalHighlightContribution.ID, TerminalHighlightContribution, false); + +// #endregion diff --git a/src/vs/workbench/contrib/terminalContrib/links/browser/terminal.links.contribution.ts b/src/vs/workbench/contrib/terminalContrib/links/browser/terminal.links.contribution.ts index dbdaf9200a000..89d73f49f2508 100644 --- a/src/vs/workbench/contrib/terminalContrib/links/browser/terminal.links.contribution.ts +++ b/src/vs/workbench/contrib/terminalContrib/links/browser/terminal.links.contribution.ts @@ -16,7 +16,7 @@ import { IDetachedTerminalInstance, ITerminalContribution, ITerminalInstance, IX import { registerActiveInstanceAction } from 'vs/workbench/contrib/terminal/browser/terminalActions'; import { registerTerminalContribution } from 'vs/workbench/contrib/terminal/browser/terminalExtensions'; import { TerminalWidgetManager } from 'vs/workbench/contrib/terminal/browser/widgets/widgetManager'; -import { ITerminalProcessInfo, ITerminalProcessManager, TerminalCommandId, isTerminalProcessManager } from 'vs/workbench/contrib/terminal/common/terminal'; +import { ITerminalProcessInfo, ITerminalProcessManager, isTerminalProcessManager } 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 { ITerminalLinkProviderService } from 'vs/workbench/contrib/terminalContrib/links/browser/links'; @@ -25,9 +25,16 @@ import { TerminalLinkProviderService } from 'vs/workbench/contrib/terminalContri import { TerminalLinkQuickpick } from 'vs/workbench/contrib/terminalContrib/links/browser/terminalLinkQuickpick'; import { TerminalLinkResolver } from 'vs/workbench/contrib/terminalContrib/links/browser/terminalLinkResolver'; import type { Terminal as RawXtermTerminal } from '@xterm/xterm'; +import { TerminalLinksCommandId } from 'vs/workbench/contrib/terminalContrib/links/common/terminal.links'; + +// #region Services registerSingleton(ITerminalLinkProviderService, TerminalLinkProviderService, InstantiationType.Delayed); +// #endregion + +// #region Terminal Contributions + class TerminalLinkContribution extends DisposableStore implements ITerminalContribution { static readonly ID = 'terminal.link'; @@ -103,10 +110,14 @@ class TerminalLinkContribution extends DisposableStore implements ITerminalContr registerTerminalContribution(TerminalLinkContribution.ID, TerminalLinkContribution, true); +// #endregion + +// #region Actions + const category = terminalStrings.actionCategory; registerActiveInstanceAction({ - id: TerminalCommandId.OpenDetectedLink, + id: TerminalLinksCommandId.OpenDetectedLink, title: localize2('workbench.action.terminal.openDetectedLink', 'Open Detected Link...'), f1: true, category, @@ -124,7 +135,7 @@ registerActiveInstanceAction({ run: (activeInstance) => TerminalLinkContribution.get(activeInstance)?.showLinkQuickpick() }); registerActiveInstanceAction({ - id: TerminalCommandId.OpenWebLink, + id: TerminalLinksCommandId.OpenWebLink, title: localize2('workbench.action.terminal.openLastUrlLink', 'Open Last URL Link'), metadata: { description: localize2('workbench.action.terminal.openLastUrlLink.description', 'Opens the last detected URL/URI link in the terminal') @@ -135,10 +146,12 @@ registerActiveInstanceAction({ run: (activeInstance) => TerminalLinkContribution.get(activeInstance)?.openRecentLink('url') }); registerActiveInstanceAction({ - id: TerminalCommandId.OpenFileLink, + id: TerminalLinksCommandId.OpenFileLink, title: localize2('workbench.action.terminal.openLastLocalFileLink', 'Open Last Local File Link'), f1: true, category, precondition: TerminalContextKeys.terminalHasBeenCreated, run: (activeInstance) => TerminalLinkContribution.get(activeInstance)?.openRecentLink('localFile') }); + +// #endregion diff --git a/src/vs/workbench/contrib/terminalContrib/links/common/terminal.links.ts b/src/vs/workbench/contrib/terminalContrib/links/common/terminal.links.ts new file mode 100644 index 0000000000000..2c0be865dea16 --- /dev/null +++ b/src/vs/workbench/contrib/terminalContrib/links/common/terminal.links.ts @@ -0,0 +1,11 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +export const enum TerminalLinksCommandId { + OpenDetectedLink = 'workbench.action.terminal.openDetectedLink', + OpenWordLink = 'workbench.action.terminal.openWordLink', + OpenFileLink = 'workbench.action.terminal.openFileLink', + OpenWebLink = 'workbench.action.terminal.openUrlLink', +} From dd9c3dfa4a3788766c8241e53172d2b708680a07 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Sun, 28 Apr 2024 06:25:44 -0700 Subject: [PATCH 066/104] More more terminal typeAhead code into terminalContrib --- src/vs/platform/terminal/common/terminal.ts | 4 -- .../contrib/terminal/common/terminal.ts | 6 -- .../terminal/common/terminalConfiguration.ts | 45 ++----------- .../terminal.typeAhead.contribution.ts | 8 +-- .../browser/terminalTypeAheadAddon.ts | 21 +++--- .../common/terminalTypeAheadConfiguration.ts | 66 +++++++++++++++++++ .../test/browser/terminalTypeAhead.test.ts | 7 +- 7 files changed, 89 insertions(+), 68 deletions(-) create mode 100644 src/vs/workbench/contrib/terminalContrib/typeAhead/common/terminalTypeAheadConfiguration.ts diff --git a/src/vs/platform/terminal/common/terminal.ts b/src/vs/platform/terminal/common/terminal.ts index eb7f36e8b792a..3fb6a4cfae730 100644 --- a/src/vs/platform/terminal/common/terminal.ts +++ b/src/vs/platform/terminal/common/terminal.ts @@ -97,10 +97,6 @@ export const enum TerminalSettingId { EnableFileLinks = 'terminal.integrated.enableFileLinks', AllowedLinkSchemes = 'terminal.integrated.allowedLinkSchemes', UnicodeVersion = 'terminal.integrated.unicodeVersion', - LocalEchoLatencyThreshold = 'terminal.integrated.localEchoLatencyThreshold', - LocalEchoEnabled = 'terminal.integrated.localEchoEnabled', - LocalEchoExcludePrograms = 'terminal.integrated.localEchoExcludePrograms', - LocalEchoStyle = 'terminal.integrated.localEchoStyle', EnablePersistentSessions = 'terminal.integrated.enablePersistentSessions', PersistentSessionReviveProcess = 'terminal.integrated.persistentSessionReviveProcess', HideOnStartup = 'terminal.integrated.hideOnStartup', diff --git a/src/vs/workbench/contrib/terminal/common/terminal.ts b/src/vs/workbench/contrib/terminal/common/terminal.ts index 9ba0b3a2d562e..cb56402e16268 100644 --- a/src/vs/workbench/contrib/terminal/common/terminal.ts +++ b/src/vs/workbench/contrib/terminal/common/terminal.ts @@ -183,10 +183,6 @@ export interface ITerminalConfiguration { enableFileLinks: 'off' | 'on' | 'notRemote'; allowedLinkSchemes: string[]; unicodeVersion: '6' | '11'; - localEchoLatencyThreshold: number; - localEchoExcludePrograms: ReadonlyArray; - localEchoEnabled: 'auto' | 'on' | 'off'; - localEchoStyle: 'bold' | 'dim' | 'italic' | 'underlined' | 'inverted' | string; enablePersistentSessions: boolean; tabs: { enabled: boolean; @@ -215,8 +211,6 @@ export interface ITerminalConfiguration { rescaleOverlappingGlyphs: boolean; } -export const DEFAULT_LOCAL_ECHO_EXCLUDE: ReadonlyArray = ['vim', 'vi', 'nano', 'tmux']; - export interface ITerminalFont { fontFamily: string; fontSize: number; diff --git a/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts b/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts index 9f7b3295e11f6..407251c7fa601 100644 --- a/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts +++ b/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts @@ -5,7 +5,7 @@ import { ConfigurationScope, Extensions, IConfigurationNode, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry'; import { localize } from 'vs/nls'; -import { DEFAULT_LETTER_SPACING, DEFAULT_LINE_HEIGHT, DEFAULT_COMMANDS_TO_SKIP_SHELL, SUGGESTIONS_FONT_WEIGHT, MINIMUM_FONT_WEIGHT, MAXIMUM_FONT_WEIGHT, DEFAULT_LOCAL_ECHO_EXCLUDE } from 'vs/workbench/contrib/terminal/common/terminal'; +import { DEFAULT_LETTER_SPACING, DEFAULT_LINE_HEIGHT, DEFAULT_COMMANDS_TO_SKIP_SHELL, SUGGESTIONS_FONT_WEIGHT, MINIMUM_FONT_WEIGHT, MAXIMUM_FONT_WEIGHT } from 'vs/workbench/contrib/terminal/common/terminal'; import { TerminalLocationString, TerminalSettingId } from 'vs/platform/terminal/common/terminal'; import { isMacintosh, isWindows } from 'vs/base/common/platform'; import { Registry } from 'vs/platform/registry/common/platform'; @@ -18,6 +18,7 @@ import { Extensions as WorkbenchExtensions, IConfigurationMigrationRegistry, Con // they need to be declared at part of the rest of the terminal configuration import { terminalAccessibilityConfiguration } from 'vs/workbench/contrib/terminalContrib/accessibility/common/terminalAccessibilityConfiguration'; // eslint-disable-line local/code-import-patterns import { terminalStickyScrollConfiguration } from 'vs/workbench/contrib/terminalContrib/stickyScroll/common/terminalStickyScrollConfiguration'; // eslint-disable-line local/code-import-patterns +import { terminalTypeAheadConfiguration } from 'vs/workbench/contrib/terminalContrib/typeAhead/common/terminalTypeAheadConfiguration'; // eslint-disable-line local/code-import-patterns const terminalDescriptors = '\n- ' + [ '`\${cwd}`: ' + localize("cwd", "the terminal's current working directory"), @@ -518,45 +519,6 @@ const terminalConfiguration: IConfigurationNode = { default: '11', description: localize('terminal.integrated.unicodeVersion', "Controls what version of Unicode to use when evaluating the width of characters in the terminal. If you experience emoji or other wide characters not taking up the right amount of space or backspace either deleting too much or too little then you may want to try tweaking this setting.") }, - [TerminalSettingId.LocalEchoLatencyThreshold]: { - description: localize('terminal.integrated.localEchoLatencyThreshold', "Length of network delay, in milliseconds, where local edits will be echoed on the terminal without waiting for server acknowledgement. If '0', local echo will always be on, and if '-1' it will be disabled."), - type: 'integer', - minimum: -1, - default: 30, - }, - [TerminalSettingId.LocalEchoEnabled]: { - markdownDescription: localize('terminal.integrated.localEchoEnabled', "When local echo should be enabled. This will override {0}", '`#terminal.integrated.localEchoLatencyThreshold#`'), - type: 'string', - enum: ['on', 'off', 'auto'], - enumDescriptions: [ - localize('terminal.integrated.localEchoEnabled.on', "Always enabled"), - localize('terminal.integrated.localEchoEnabled.off', "Always disabled"), - localize('terminal.integrated.localEchoEnabled.auto', "Enabled only for remote workspaces") - ], - default: 'auto' - }, - [TerminalSettingId.LocalEchoExcludePrograms]: { - description: localize('terminal.integrated.localEchoExcludePrograms', "Local echo will be disabled when any of these program names are found in the terminal title."), - type: 'array', - items: { - type: 'string', - uniqueItems: true - }, - default: DEFAULT_LOCAL_ECHO_EXCLUDE, - }, - [TerminalSettingId.LocalEchoStyle]: { - description: localize('terminal.integrated.localEchoStyle', "Terminal style of locally echoed text; either a font style or an RGB color."), - default: 'dim', - anyOf: [ - { - enum: ['bold', 'dim', 'italic', 'underlined', 'inverted', '#ff0000'], - }, - { - type: 'string', - format: 'color-hex', - } - ] - }, [TerminalSettingId.EnablePersistentSessions]: { description: localize('terminal.integrated.enablePersistentSessions', "Persist terminal sessions/history for the workspace across window reloads."), type: 'boolean', @@ -673,7 +635,8 @@ const terminalConfiguration: IConfigurationNode = { default: false }, ...terminalAccessibilityConfiguration, - ...terminalStickyScrollConfiguration + ...terminalStickyScrollConfiguration, + ...terminalTypeAheadConfiguration, } }; diff --git a/src/vs/workbench/contrib/terminalContrib/typeAhead/browser/terminal.typeAhead.contribution.ts b/src/vs/workbench/contrib/terminalContrib/typeAhead/browser/terminal.typeAhead.contribution.ts index 1851d36cf7d3b..6977568149c0d 100644 --- a/src/vs/workbench/contrib/terminalContrib/typeAhead/browser/terminal.typeAhead.contribution.ts +++ b/src/vs/workbench/contrib/terminalContrib/typeAhead/browser/terminal.typeAhead.contribution.ts @@ -6,13 +6,13 @@ import { DisposableStore, toDisposable } from 'vs/base/common/lifecycle'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { TerminalSettingId } from 'vs/platform/terminal/common/terminal'; import { ITerminalContribution, ITerminalInstance, IXtermTerminal } from 'vs/workbench/contrib/terminal/browser/terminal'; import { registerTerminalContribution } from 'vs/workbench/contrib/terminal/browser/terminalExtensions'; import { TerminalWidgetManager } from 'vs/workbench/contrib/terminal/browser/widgets/widgetManager'; import { TypeAheadAddon } from 'vs/workbench/contrib/terminalContrib/typeAhead/browser/terminalTypeAheadAddon'; -import { ITerminalConfiguration, ITerminalProcessManager, TERMINAL_CONFIG_SECTION } from 'vs/workbench/contrib/terminal/common/terminal'; +import { ITerminalProcessManager, TERMINAL_CONFIG_SECTION } from 'vs/workbench/contrib/terminal/common/terminal'; import type { Terminal as RawXtermTerminal } from '@xterm/xterm'; +import { TerminalTypeAheadSettingId, type ITerminalTypeAheadConfiguration } from 'vs/workbench/contrib/terminalContrib/typeAhead/common/terminalTypeAheadConfiguration'; class TerminalTypeAheadContribution extends DisposableStore implements ITerminalContribution { static readonly ID = 'terminal.typeAhead'; @@ -37,7 +37,7 @@ class TerminalTypeAheadContribution extends DisposableStore implements ITerminal xtermReady(xterm: IXtermTerminal & { raw: RawXtermTerminal }): void { this._loadTypeAheadAddon(xterm.raw); this.add(this._configurationService.onDidChangeConfiguration(e => { - if (e.affectsConfiguration(TerminalSettingId.LocalEchoEnabled)) { + if (e.affectsConfiguration(TerminalTypeAheadSettingId.LocalEchoEnabled)) { this._loadTypeAheadAddon(xterm.raw); } })); @@ -49,7 +49,7 @@ class TerminalTypeAheadContribution extends DisposableStore implements ITerminal } private _loadTypeAheadAddon(xterm: RawXtermTerminal): void { - const enabled = this._configurationService.getValue(TERMINAL_CONFIG_SECTION).localEchoEnabled; + const enabled = this._configurationService.getValue(TERMINAL_CONFIG_SECTION).localEchoEnabled; const isRemote = !!this._processManager.remoteAuthority; if (enabled === 'off' || enabled === 'auto' && !isRemote) { this._addon?.dispose(); diff --git a/src/vs/workbench/contrib/terminalContrib/typeAhead/browser/terminalTypeAheadAddon.ts b/src/vs/workbench/contrib/terminalContrib/typeAhead/browser/terminalTypeAheadAddon.ts index d6d672c9aca09..6a0656d8f1b96 100644 --- a/src/vs/workbench/contrib/terminalContrib/typeAhead/browser/terminalTypeAheadAddon.ts +++ b/src/vs/workbench/contrib/terminalContrib/typeAhead/browser/terminalTypeAheadAddon.ts @@ -12,8 +12,9 @@ import { escapeRegExpCharacters } from 'vs/base/common/strings'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { XtermAttributes, IXtermCore } from 'vs/workbench/contrib/terminal/browser/xterm-private'; -import { DEFAULT_LOCAL_ECHO_EXCLUDE, IBeforeProcessDataEvent, ITerminalConfiguration, ITerminalProcessManager, TERMINAL_CONFIG_SECTION } from 'vs/workbench/contrib/terminal/common/terminal'; +import { IBeforeProcessDataEvent, ITerminalProcessManager, TERMINAL_CONFIG_SECTION } from 'vs/workbench/contrib/terminal/common/terminal'; import type { IBuffer, IBufferCell, IDisposable, ITerminalAddon, Terminal } from '@xterm/xterm'; +import { DEFAULT_LOCAL_ECHO_EXCLUDE, type ITerminalTypeAheadConfiguration } from 'vs/workbench/contrib/terminalContrib/typeAhead/common/terminalTypeAheadConfiguration'; const enum VT { Esc = '\x1b', @@ -1134,7 +1135,7 @@ class TypeAheadStyle implements IDisposable { undo!: string; private _csiHandler?: IDisposable; - constructor(value: ITerminalConfiguration['localEchoStyle'], private readonly _terminal: Terminal) { + constructor(value: ITerminalTypeAheadConfiguration['localEchoStyle'], private readonly _terminal: Terminal) { this.onUpdate(value); } @@ -1240,7 +1241,7 @@ class TypeAheadStyle implements IDisposable { /** * Updates the current typeahead style. */ - onUpdate(style: ITerminalConfiguration['localEchoStyle']) { + onUpdate(style: ITerminalTypeAheadConfiguration['localEchoStyle']) { const { applyArgs, undoArgs } = this._getArgs(style); this._applyArgs = applyArgs; this._undoArgs = this._originalUndoArgs = undoArgs; @@ -1248,7 +1249,7 @@ class TypeAheadStyle implements IDisposable { this.undo = TypeAheadStyle._compileArgs(this._undoArgs); } - private _getArgs(style: ITerminalConfiguration['localEchoStyle']) { + private _getArgs(style: ITerminalTypeAheadConfiguration['localEchoStyle']) { switch (style) { case 'bold': return { applyArgs: [1], undoArgs: [22] }; @@ -1289,8 +1290,8 @@ export const enum CharPredictState { export class TypeAheadAddon extends Disposable implements ITerminalAddon { private _typeaheadStyle?: TypeAheadStyle; - private _typeaheadThreshold = this._configurationService.getValue(TERMINAL_CONFIG_SECTION).localEchoLatencyThreshold; - private _excludeProgramRe = compileExcludeRegexp(this._configurationService.getValue(TERMINAL_CONFIG_SECTION).localEchoExcludePrograms); + private _typeaheadThreshold = this._configurationService.getValue(TERMINAL_CONFIG_SECTION).localEchoLatencyThreshold; + private _excludeProgramRe = compileExcludeRegexp(this._configurationService.getValue(TERMINAL_CONFIG_SECTION).localEchoExcludePrograms); protected _lastRow?: { y: number; startingX: number; endingX: number; charState: CharPredictState }; protected _timeline?: PredictionTimeline; private _terminalTitle = ''; @@ -1311,7 +1312,7 @@ export class TypeAheadAddon extends Disposable implements ITerminalAddon { } activate(terminal: Terminal): void { - const style = this._typeaheadStyle = this._register(new TypeAheadStyle(this._configurationService.getValue(TERMINAL_CONFIG_SECTION).localEchoStyle, terminal)); + const style = this._typeaheadStyle = this._register(new TypeAheadStyle(this._configurationService.getValue(TERMINAL_CONFIG_SECTION).localEchoStyle, terminal)); const timeline = this._timeline = new PredictionTimeline(terminal, this._typeaheadStyle); const stats = this.stats = this._register(new PredictionStats(this._timeline)); @@ -1328,9 +1329,9 @@ export class TypeAheadAddon extends Disposable implements ITerminalAddon { })); this._register(this._configurationService.onDidChangeConfiguration(e => { if (e.affectsConfiguration(TERMINAL_CONFIG_SECTION)) { - style.onUpdate(this._configurationService.getValue(TERMINAL_CONFIG_SECTION).localEchoStyle); - this._typeaheadThreshold = this._configurationService.getValue(TERMINAL_CONFIG_SECTION).localEchoLatencyThreshold; - this._excludeProgramRe = compileExcludeRegexp(this._configurationService.getValue(TERMINAL_CONFIG_SECTION).localEchoExcludePrograms); + style.onUpdate(this._configurationService.getValue(TERMINAL_CONFIG_SECTION).localEchoStyle); + this._typeaheadThreshold = this._configurationService.getValue(TERMINAL_CONFIG_SECTION).localEchoLatencyThreshold; + this._excludeProgramRe = compileExcludeRegexp(this._configurationService.getValue(TERMINAL_CONFIG_SECTION).localEchoExcludePrograms); this._reevaluatePredictorState(stats, timeline); } })); diff --git a/src/vs/workbench/contrib/terminalContrib/typeAhead/common/terminalTypeAheadConfiguration.ts b/src/vs/workbench/contrib/terminalContrib/typeAhead/common/terminalTypeAheadConfiguration.ts new file mode 100644 index 0000000000000..6b4b2d9f917e4 --- /dev/null +++ b/src/vs/workbench/contrib/terminalContrib/typeAhead/common/terminalTypeAheadConfiguration.ts @@ -0,0 +1,66 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import type { IStringDictionary } from 'vs/base/common/collections'; +import { localize } from 'vs/nls'; +import type { IConfigurationPropertySchema } from 'vs/platform/configuration/common/configurationRegistry'; + +export const DEFAULT_LOCAL_ECHO_EXCLUDE: ReadonlyArray = ['vim', 'vi', 'nano', 'tmux']; + +export const enum TerminalTypeAheadSettingId { + LocalEchoLatencyThreshold = 'terminal.integrated.localEchoLatencyThreshold', + LocalEchoEnabled = 'terminal.integrated.localEchoEnabled', + LocalEchoExcludePrograms = 'terminal.integrated.localEchoExcludePrograms', + LocalEchoStyle = 'terminal.integrated.localEchoStyle', +} + +export interface ITerminalTypeAheadConfiguration { + localEchoLatencyThreshold: number; + localEchoExcludePrograms: ReadonlyArray; + localEchoEnabled: 'auto' | 'on' | 'off'; + localEchoStyle: 'bold' | 'dim' | 'italic' | 'underlined' | 'inverted' | string; +} + +export const terminalTypeAheadConfiguration: IStringDictionary = { + [TerminalTypeAheadSettingId.LocalEchoLatencyThreshold]: { + description: localize('terminal.integrated.localEchoLatencyThreshold', "Length of network delay, in milliseconds, where local edits will be echoed on the terminal without waiting for server acknowledgement. If '0', local echo will always be on, and if '-1' it will be disabled."), + type: 'integer', + minimum: -1, + default: 30, + }, + [TerminalTypeAheadSettingId.LocalEchoEnabled]: { + markdownDescription: localize('terminal.integrated.localEchoEnabled', "When local echo should be enabled. This will override {0}", '`#terminal.integrated.localEchoLatencyThreshold#`'), + type: 'string', + enum: ['on', 'off', 'auto'], + enumDescriptions: [ + localize('terminal.integrated.localEchoEnabled.on', "Always enabled"), + localize('terminal.integrated.localEchoEnabled.off', "Always disabled"), + localize('terminal.integrated.localEchoEnabled.auto', "Enabled only for remote workspaces") + ], + default: 'auto' + }, + [TerminalTypeAheadSettingId.LocalEchoExcludePrograms]: { + description: localize('terminal.integrated.localEchoExcludePrograms', "Local echo will be disabled when any of these program names are found in the terminal title."), + type: 'array', + items: { + type: 'string', + uniqueItems: true + }, + default: DEFAULT_LOCAL_ECHO_EXCLUDE, + }, + [TerminalTypeAheadSettingId.LocalEchoStyle]: { + description: localize('terminal.integrated.localEchoStyle', "Terminal style of locally echoed text; either a font style or an RGB color."), + default: 'dim', + anyOf: [ + { + enum: ['bold', 'dim', 'italic', 'underlined', 'inverted', '#ff0000'], + }, + { + type: 'string', + format: 'color-hex', + } + ] + }, +}; diff --git a/src/vs/workbench/contrib/terminalContrib/typeAhead/test/browser/terminalTypeAhead.test.ts b/src/vs/workbench/contrib/terminalContrib/typeAhead/test/browser/terminalTypeAhead.test.ts index c6524b94eb2bd..86972f65fa702 100644 --- a/src/vs/workbench/contrib/terminalContrib/typeAhead/test/browser/terminalTypeAhead.test.ts +++ b/src/vs/workbench/contrib/terminalContrib/typeAhead/test/browser/terminalTypeAhead.test.ts @@ -8,11 +8,12 @@ import type { IBuffer, Terminal } from '@xterm/xterm'; import { SinonStub, stub, useFakeTimers } from 'sinon'; import { Emitter } from 'vs/base/common/event'; import { CharPredictState, IPrediction, PredictionStats, TypeAheadAddon } from 'vs/workbench/contrib/terminalContrib/typeAhead/browser/terminalTypeAheadAddon'; -import { DEFAULT_LOCAL_ECHO_EXCLUDE, IBeforeProcessDataEvent, ITerminalConfiguration, ITerminalProcessManager } from 'vs/workbench/contrib/terminal/common/terminal'; +import { IBeforeProcessDataEvent, ITerminalProcessManager } from 'vs/workbench/contrib/terminal/common/terminal'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService'; import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils'; import { DisposableStore } from 'vs/base/common/lifecycle'; +import { DEFAULT_LOCAL_ECHO_EXCLUDE, type ITerminalTypeAheadConfiguration } from 'vs/workbench/contrib/terminalContrib/typeAhead/common/terminalTypeAheadConfiguration'; const CSI = `\x1b[`; @@ -84,7 +85,7 @@ suite('Workbench - Terminal Typeahead', () => { suite('timeline', () => { let onBeforeProcessData: Emitter; let publicLog: SinonStub; - let config: ITerminalConfiguration; + let config: ITerminalTypeAheadConfiguration; let addon: TestTypeAheadAddon; const predictedHelloo = [ @@ -103,7 +104,7 @@ suite('Workbench - Terminal Typeahead', () => { setup(() => { onBeforeProcessData = ds.add(new Emitter()); - config = upcastPartial({ + config = upcastPartial({ localEchoStyle: 'italic', localEchoLatencyThreshold: 0, localEchoExcludePrograms: DEFAULT_LOCAL_ECHO_EXCLUDE, From 09712f7191b51be8eee66e1f3dece175aedee0a9 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Sun, 28 Apr 2024 06:29:46 -0700 Subject: [PATCH 067/104] More more terminal zoom code into terminalContrib --- src/vs/platform/terminal/common/terminal.ts | 1 - .../contrib/terminal/common/terminal.ts | 3 -- .../terminal/common/terminalConfiguration.ts | 9 ++---- .../browser/terminal.zoom.contribution.ts | 13 +++++---- .../zoom/common/terminal.zoom.ts | 29 +++++++++++++++++++ 5 files changed, 38 insertions(+), 17 deletions(-) create mode 100644 src/vs/workbench/contrib/terminalContrib/zoom/common/terminal.zoom.ts diff --git a/src/vs/platform/terminal/common/terminal.ts b/src/vs/platform/terminal/common/terminal.ts index 3fb6a4cfae730..b2dc5e44b2b97 100644 --- a/src/vs/platform/terminal/common/terminal.ts +++ b/src/vs/platform/terminal/common/terminal.ts @@ -116,7 +116,6 @@ export const enum TerminalSettingId { SmoothScrolling = 'terminal.integrated.smoothScrolling', IgnoreBracketedPasteMode = 'terminal.integrated.ignoreBracketedPasteMode', FocusAfterRun = 'terminal.integrated.focusAfterRun', - MouseWheelZoom = 'terminal.integrated.mouseWheelZoom', // Debug settings that are hidden from user diff --git a/src/vs/workbench/contrib/terminal/common/terminal.ts b/src/vs/workbench/contrib/terminal/common/terminal.ts index cb56402e16268..14926bfaec2ea 100644 --- a/src/vs/workbench/contrib/terminal/common/terminal.ts +++ b/src/vs/workbench/contrib/terminal/common/terminal.ts @@ -481,9 +481,6 @@ export const enum TerminalCommandId { ShowEnvironmentContributions = 'workbench.action.terminal.showEnvironmentContributions', StartVoice = 'workbench.action.terminal.startVoice', StopVoice = 'workbench.action.terminal.stopVoice', - FontZoomIn = 'workbench.action.terminal.fontZoomIn', - FontZoomOut = 'workbench.action.terminal.fontZoomOut', - FontZoomReset = 'workbench.action.terminal.fontZoomReset', } export const DEFAULT_COMMANDS_TO_SKIP_SHELL: string[] = [ diff --git a/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts b/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts index 407251c7fa601..1b24f288512ab 100644 --- a/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts +++ b/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts @@ -19,6 +19,7 @@ import { Extensions as WorkbenchExtensions, IConfigurationMigrationRegistry, Con import { terminalAccessibilityConfiguration } from 'vs/workbench/contrib/terminalContrib/accessibility/common/terminalAccessibilityConfiguration'; // eslint-disable-line local/code-import-patterns import { terminalStickyScrollConfiguration } from 'vs/workbench/contrib/terminalContrib/stickyScroll/common/terminalStickyScrollConfiguration'; // eslint-disable-line local/code-import-patterns import { terminalTypeAheadConfiguration } from 'vs/workbench/contrib/terminalContrib/typeAhead/common/terminalTypeAheadConfiguration'; // eslint-disable-line local/code-import-patterns +import { terminalZoomConfiguration } from 'vs/workbench/contrib/terminalContrib/zoom/common/terminal.zoom'; // eslint-disable-line local/code-import-patterns const terminalDescriptors = '\n- ' + [ '`\${cwd}`: ' + localize("cwd", "the terminal's current working directory"), @@ -627,16 +628,10 @@ const terminalConfiguration: IConfigurationNode = { localize('terminal.integrated.focusAfterRun.none', "Do nothing."), ] }, - [TerminalSettingId.MouseWheelZoom]: { - markdownDescription: isMacintosh - ? localize('terminal.integrated.mouseWheelZoom.mac', "Zoom the font of the terminal when using mouse wheel and holding `Cmd`.") - : localize('terminal.integrated.mouseWheelZoom', "Zoom the font of the terminal when using mouse wheel and holding `Ctrl`."), - type: 'boolean', - default: false - }, ...terminalAccessibilityConfiguration, ...terminalStickyScrollConfiguration, ...terminalTypeAheadConfiguration, + ...terminalZoomConfiguration, } }; diff --git a/src/vs/workbench/contrib/terminalContrib/zoom/browser/terminal.zoom.contribution.ts b/src/vs/workbench/contrib/terminalContrib/zoom/browser/terminal.zoom.contribution.ts index aed5f68e6bbeb..12f2a06f6870c 100644 --- a/src/vs/workbench/contrib/terminalContrib/zoom/browser/terminal.zoom.contribution.ts +++ b/src/vs/workbench/contrib/terminalContrib/zoom/browser/terminal.zoom.contribution.ts @@ -13,12 +13,13 @@ import { TerminalSettingId } from 'vs/platform/terminal/common/terminal'; import { IDetachedTerminalInstance, ITerminalContribution, ITerminalInstance, IXtermTerminal } from 'vs/workbench/contrib/terminal/browser/terminal'; import { registerTerminalContribution } from 'vs/workbench/contrib/terminal/browser/terminalExtensions'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { ITerminalProcessInfo, ITerminalProcessManager, TerminalCommandId } from 'vs/workbench/contrib/terminal/common/terminal'; +import { ITerminalProcessInfo, ITerminalProcessManager } from 'vs/workbench/contrib/terminal/common/terminal'; import { TerminalWidgetManager } from 'vs/workbench/contrib/terminal/browser/widgets/widgetManager'; import { registerTerminalAction } from 'vs/workbench/contrib/terminal/browser/terminalActions'; import { localize2 } from 'vs/nls'; import { isNumber } from 'vs/base/common/types'; import { defaultTerminalFontSize } from 'vs/workbench/contrib/terminal/common/terminalConfiguration'; +import { TerminalZoomCommandId, TerminalZoomSettingId } from 'vs/workbench/contrib/terminalContrib/zoom/common/terminal.zoom'; class TerminalMouseWheelZoomContribution extends Disposable implements ITerminalContribution { static readonly ID = 'terminal.mouseWheelZoom'; @@ -46,8 +47,8 @@ class TerminalMouseWheelZoomContribution extends Disposable implements ITerminal xtermOpen(xterm: IXtermTerminal & { raw: RawXtermTerminal }): void { this._register(Event.runAndSubscribe(this._configurationService.onDidChangeConfiguration, e => { - if (!e || e.affectsConfiguration(TerminalSettingId.MouseWheelZoom)) { - if (!!this._configurationService.getValue(TerminalSettingId.MouseWheelZoom)) { + if (!e || e.affectsConfiguration(TerminalZoomSettingId.MouseWheelZoom)) { + if (!!this._configurationService.getValue(TerminalZoomSettingId.MouseWheelZoom)) { this._setupMouseWheelZoomListener(xterm.raw); } else { this._listener.clear(); @@ -125,7 +126,7 @@ class TerminalMouseWheelZoomContribution extends Disposable implements ITerminal registerTerminalContribution(TerminalMouseWheelZoomContribution.ID, TerminalMouseWheelZoomContribution, true); registerTerminalAction({ - id: TerminalCommandId.FontZoomIn, + id: TerminalZoomCommandId.FontZoomIn, title: localize2('fontZoomIn', 'Increase Font Size'), run: async (c, accessor) => { const configurationService = accessor.get(IConfigurationService); @@ -137,7 +138,7 @@ registerTerminalAction({ }); registerTerminalAction({ - id: TerminalCommandId.FontZoomOut, + id: TerminalZoomCommandId.FontZoomOut, title: localize2('fontZoomOut', 'Decrease Font Size'), run: async (c, accessor) => { const configurationService = accessor.get(IConfigurationService); @@ -149,7 +150,7 @@ registerTerminalAction({ }); registerTerminalAction({ - id: TerminalCommandId.FontZoomReset, + id: TerminalZoomCommandId.FontZoomReset, title: localize2('fontZoomReset', 'Reset Font Size'), run: async (c, accessor) => { const configurationService = accessor.get(IConfigurationService); diff --git a/src/vs/workbench/contrib/terminalContrib/zoom/common/terminal.zoom.ts b/src/vs/workbench/contrib/terminalContrib/zoom/common/terminal.zoom.ts new file mode 100644 index 0000000000000..e7da97b2dc4f9 --- /dev/null +++ b/src/vs/workbench/contrib/terminalContrib/zoom/common/terminal.zoom.ts @@ -0,0 +1,29 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import type { IStringDictionary } from 'vs/base/common/collections'; +import { isMacintosh } from 'vs/base/common/platform'; +import { localize } from 'vs/nls'; +import type { IConfigurationPropertySchema } from 'vs/platform/configuration/common/configurationRegistry'; + +export const enum TerminalZoomCommandId { + FontZoomIn = 'workbench.action.terminal.fontZoomIn', + FontZoomOut = 'workbench.action.terminal.fontZoomOut', + FontZoomReset = 'workbench.action.terminal.fontZoomReset', +} + +export const enum TerminalZoomSettingId { + MouseWheelZoom = 'terminal.integrated.mouseWheelZoom', +} + +export const terminalZoomConfiguration: IStringDictionary = { + [TerminalZoomSettingId.MouseWheelZoom]: { + markdownDescription: isMacintosh + ? localize('terminal.integrated.mouseWheelZoom.mac', "Zoom the font of the terminal when using mouse wheel and holding `Cmd`.") + : localize('terminal.integrated.mouseWheelZoom', "Zoom the font of the terminal when using mouse wheel and holding `Ctrl`."), + type: 'boolean', + default: false + }, +}; From 5090e072216850abf3276faa212ec9a8ee35c45b Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Sun, 28 Apr 2024 10:07:01 -0700 Subject: [PATCH 068/104] Fix [ namespace completions Fixes #211578 --- .../browser/media/shellIntegration.ps1 | 6 ++++- .../terminal/browser/terminalInstance.ts | 1 + .../suggest/browser/terminalSuggestAddon.ts | 26 ++++++++++++------- .../suggest/browser/simpleCompletionItem.ts | 4 +++ 4 files changed, 26 insertions(+), 11 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/browser/media/shellIntegration.ps1 b/src/vs/workbench/contrib/terminal/browser/media/shellIntegration.ps1 index f2f50c467177b..4f34617a58620 100644 --- a/src/vs/workbench/contrib/terminal/browser/media/shellIntegration.ps1 +++ b/src/vs/workbench/contrib/terminal/browser/media/shellIntegration.ps1 @@ -178,6 +178,7 @@ function Set-MappedKeyHandlers { # and ranking on the client side with the full list of results. $result = "$([char]0x1b)]633;CompletionsPwshCommands;commands;" $result += [System.Management.Automation.CompletionCompleters]::CompleteCommand('') | ConvertTo-Json -Compress + $result += "`a" Write-Host -NoNewLine $result } } @@ -193,7 +194,10 @@ function Send-Completions { # If there is a space in the input, defer to TabExpansion2 as it's more complicated to # determine what type of completions to use - if ($completionPrefix.Contains(' ')) { + # `[` is included here as namespace commands are not included in CompleteCommand(''), + # additionally for some reason CompleteVariable('[') causes the prompt to clear and reprint + # multiple times + if ($completionPrefix.Contains(' ') -or $completionPrefix.Contains('[')) { $completions = TabExpansion2 -inputScript $completionPrefix -cursorColumn $cursorIndex if ($null -ne $completions.CompletionMatches) { $result += ";$($completions.ReplacementIndex);$($completions.ReplacementLength);$($cursorIndex);" diff --git a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts index a53fb826303cb..f0ecfbbf1b8d0 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts @@ -1242,6 +1242,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { } // Send it to the process + this._logService.debug('sending data (vscode)', text); await this._processManager.write(text); this._onDidInputData.fire(this); this._onDidSendText.fire(text); diff --git a/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon.ts b/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon.ts index 1c8f446b59f79..0db049e4b0127 100644 --- a/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon.ts +++ b/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon.ts @@ -140,7 +140,6 @@ export class SuggestAddon extends Disposable implements ITerminalAddon, ISuggest private _requestCompletions(): void { // TODO: Debounce? Prevent this flooding the channel - // if (this._terminal. this._onAcceptedCompletion.fire('\x1b[24~e'); } @@ -153,8 +152,10 @@ export class SuggestAddon extends Disposable implements ITerminalAddon, ISuggest if (!this._terminalSuggestWidgetVisibleContextKey.get()) { // If input has been added if (!this._mostRecentPromptInputState || promptInputState.cursorIndex > this._mostRecentPromptInputState.cursorIndex) { + const completionPrefix = promptInputState.value.substring(0, promptInputState.cursorIndex); + // Quick suggestions - if (promptInputState.cursorIndex === 1 || promptInputState.value.substring(0, promptInputState.cursorIndex).match(/\s[^\s]$/)) { + if (promptInputState.cursorIndex === 1 || completionPrefix.match(/([\s\[])[^\s]$/)) { // TODO: Allow the user to configure terminal quickSuggestions this._requestCompletions(); } @@ -250,7 +251,8 @@ export class SuggestAddon extends Disposable implements ITerminalAddon, ISuggest } const completions = completionList.map((e: any) => { return new SimpleCompletionItem({ - label: e.CompletionText, + label: e.ListItemText, + completionText: e.CompletionText, icon: pwshTypeToIconMap[e.ResultType], detail: e.ToolTip }); @@ -259,15 +261,16 @@ export class SuggestAddon extends Disposable implements ITerminalAddon, ISuggest this._leadingLineContent = this._promptInputModel.value.substring(0, this._promptInputModel.cursorIndex); // If there's no space it means this is a command, add cached commands list to completions - if (!this._leadingLineContent.trim().includes(' ')) { - completions.push(...this._cachedPwshCommands); - } else { + const firstChar = this._leadingLineContent.length === 0 ? '' : this._leadingLineContent[0]; + if (this._leadingLineContent.trim().includes(' ') || firstChar === '[') { replacementIndex = parseInt(args[0]); replacementLength = parseInt(args[1]); this._leadingLineContent = completions[0]?.completion.label.slice(0, replacementLength) ?? ''; + } else { + completions.push(...this._cachedPwshCommands); } + this._cursorIndexDelta = replacementIndex; - this._cursorIndexDelta = 0; const model = new SimpleCompletionModel(completions, new LineContext(this._leadingLineContent, replacementIndex), replacementIndex, replacementLength); this._handleCompletionModel(model); } @@ -285,7 +288,8 @@ export class SuggestAddon extends Disposable implements ITerminalAddon, ISuggest const completions = completionList.map((e: any) => { return new SimpleCompletionItem({ - label: e.CompletionText, + label: e.ListItemText, + completionText: e.CompletionText, icon: pwshTypeToIconMap[e.ResultType], detail: e.ToolTip }); @@ -477,11 +481,13 @@ export class SuggestAddon extends Disposable implements ITerminalAddon, ISuggest // Get the final completion on the right side of the cursor const initialInput = initialPromptInputState.value.substring(0, initialPromptInputState.cursorIndex); const lastSpaceIndex = initialInput.lastIndexOf(' '); - const finalCompletionRightSide = suggestion.item.completion.label.substring(initialPromptInputState.cursorIndex - (lastSpaceIndex === -1 ? 0 : lastSpaceIndex + 1)); + const completion = suggestion.item.completion; + const completionText = completion.completionText ?? completion.label; + const finalCompletionRightSide = completionText.substring(initialPromptInputState.cursorIndex - (lastSpaceIndex === -1 ? 0 : lastSpaceIndex + 1)); // Get the final completion on the right side of the cursor if it differs from the initial // propmt input state - let finalCompletionLeftSide = suggestion.item.completion.label.substring(0, initialPromptInputState.cursorIndex - (lastSpaceIndex === -1 ? 0 : lastSpaceIndex + 1)); + let finalCompletionLeftSide = completionText.substring(0, initialPromptInputState.cursorIndex - (lastSpaceIndex === -1 ? 0 : lastSpaceIndex + 1)); if (initialInput.endsWith(finalCompletionLeftSide)) { finalCompletionLeftSide = ''; } diff --git a/src/vs/workbench/services/suggest/browser/simpleCompletionItem.ts b/src/vs/workbench/services/suggest/browser/simpleCompletionItem.ts index 052731e56539d..3aa43e4c72711 100644 --- a/src/vs/workbench/services/suggest/browser/simpleCompletionItem.ts +++ b/src/vs/workbench/services/suggest/browser/simpleCompletionItem.ts @@ -19,6 +19,10 @@ export interface ISimpleCompletion { * The completion's detail which appears on the right of the list. */ detail?: string; + /** + * The completion's completion text which is used to actually insert the completion. + */ + completionText?: string; } export class SimpleCompletionItem { From cae932ffec02662845d0ce67ebb65425548aa92a Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Sun, 28 Apr 2024 10:17:20 -0700 Subject: [PATCH 069/104] Get [ completions replacing the correct range Fixes #211195 --- .../terminalContrib/suggest/browser/terminalSuggestAddon.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon.ts b/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon.ts index 0db049e4b0127..dedf217593186 100644 --- a/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon.ts +++ b/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon.ts @@ -479,15 +479,15 @@ export class SuggestAddon extends Disposable implements ITerminalAddon, ISuggest const additionalInput = currentPromptInputState.value.substring(initialPromptInputState.cursorIndex, currentPromptInputState.cursorIndex); // Get the final completion on the right side of the cursor - const initialInput = initialPromptInputState.value.substring(0, initialPromptInputState.cursorIndex); + const initialInput = initialPromptInputState.value.substring(0, (this._leadingLineContent?.length ?? 0)); const lastSpaceIndex = initialInput.lastIndexOf(' '); const completion = suggestion.item.completion; const completionText = completion.completionText ?? completion.label; - const finalCompletionRightSide = completionText.substring(initialPromptInputState.cursorIndex - (lastSpaceIndex === -1 ? 0 : lastSpaceIndex + 1)); + const finalCompletionRightSide = completionText.substring((this._leadingLineContent?.length ?? 0) - (lastSpaceIndex === -1 ? 0 : lastSpaceIndex + 1)); // Get the final completion on the right side of the cursor if it differs from the initial // propmt input state - let finalCompletionLeftSide = completionText.substring(0, initialPromptInputState.cursorIndex - (lastSpaceIndex === -1 ? 0 : lastSpaceIndex + 1)); + let finalCompletionLeftSide = completionText.substring(0, (this._leadingLineContent?.length ?? 0) - (lastSpaceIndex === -1 ? 0 : lastSpaceIndex + 1)); if (initialInput.endsWith(finalCompletionLeftSide)) { finalCompletionLeftSide = ''; } From bce484e4e4ab4315e5135f4fe1881791ed77ea46 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Sun, 28 Apr 2024 22:31:52 -0700 Subject: [PATCH 070/104] Fix some markdown `fillInIncompleteTokens` cases (#211593) * Fix markdown patching for link target with incomplete argument * Fix extra incomplete constructs inside link text * Make link target patching more strict * Patch up markdown inside lists And fix links more --- src/vs/base/browser/markdownRenderer.ts | 165 +++++++++++++----- .../test/browser/markdownRenderer.test.ts | 142 ++++++++++++++- 2 files changed, 261 insertions(+), 46 deletions(-) diff --git a/src/vs/base/browser/markdownRenderer.ts b/src/vs/base/browser/markdownRenderer.ts index fe822fe1a61c1..76c1afb4e3948 100644 --- a/src/vs/base/browser/markdownRenderer.ts +++ b/src/vs/base/browser/markdownRenderer.ts @@ -588,34 +588,62 @@ function mergeRawTokenText(tokens: marked.Token[]): string { return mergedTokenText; } -function completeSingleLinePattern(token: marked.Tokens.ListItem | marked.Tokens.Paragraph): marked.Token | undefined { - for (let i = 0; i < token.tokens.length; i++) { +function completeSingleLinePattern(token: marked.Tokens.Text | marked.Tokens.Paragraph): marked.Token | undefined { + if (!token.tokens) { + return undefined; + } + + for (let i = token.tokens.length - 1; i >= 0; i--) { const subtoken = token.tokens[i]; if (subtoken.type === 'text') { const lines = subtoken.raw.split('\n'); const lastLine = lines[lines.length - 1]; if (lastLine.includes('`')) { return completeCodespan(token); - } else if (lastLine.includes('**')) { + } + + else if (lastLine.includes('**')) { return completeDoublestar(token); - } else if (lastLine.match(/\*\w/)) { + } + + else if (lastLine.match(/\*\w/)) { return completeStar(token); - } else if (lastLine.match(/(^|\s)__\w/)) { + } + + else if (lastLine.match(/(^|\s)__\w/)) { return completeDoubleUnderscore(token); - } else if (lastLine.match(/(^|\s)_\w/)) { + } + + else if (lastLine.match(/(^|\s)_\w/)) { return completeUnderscore(token); - } else if (lastLine.match(/(^|\s)\[.*\]\(\w*/)) { + } + + else if ( + // Text with start of link target + hasLinkTextAndStartOfLinkTarget(lastLine) || + // This token doesn't have the link text, eg if it contains other markdown constructs that are in other subtokens. + // But some preceding token does have an unbalanced [ at least + hasStartOfLinkTargetAndNoLinkText(lastLine) && token.tokens.slice(0, i).some(t => t.type === 'text' && t.raw.match(/\[[^\]]*$/)) + ) { const nextTwoSubTokens = token.tokens.slice(i + 1); - if (nextTwoSubTokens[0]?.type === 'link' && nextTwoSubTokens[1]?.type === 'text' && nextTwoSubTokens[1].raw.match(/^ *"[^"]*$/)) { - // A markdown link can look like - // [link text](https://microsoft.com "more text") - // Where "more text" is a title for the link or an argument to a vscode command link + + // A markdown link can look like + // [link text](https://microsoft.com "more text") + // Where "more text" is a title for the link or an argument to a vscode command link + if ( + // If the link was parsed as a link, then look for a link token and a text token with a quote + nextTwoSubTokens[0]?.type === 'link' && nextTwoSubTokens[1]?.type === 'text' && nextTwoSubTokens[1].raw.match(/^ *"[^"]*$/) || + // And if the link was not parsed as a link (eg command link), just look for a single quote in this token + lastLine.match(/^[^"]* +"[^"]*$/) + ) { + return completeLinkTargetArg(token); } return completeLinkTarget(token); - } else if (hasStartOfLinkTarget(lastLine)) { - return completeLinkTarget(token); - } else if (lastLine.match(/(^|\s)\[\w/) && !token.tokens.slice(i + 1).some(t => hasStartOfLinkTarget(t.raw))) { + } + + // Contains the start of link text, and no following tokens contain the link target + else if (lastLine.match(/(^|\s)\[\w*/)) { return completeLinkText(token); } } @@ -624,31 +652,90 @@ function completeSingleLinePattern(token: marked.Tokens.ListItem | marked.Tokens return undefined; } -function hasStartOfLinkTarget(str: string): boolean { +function hasLinkTextAndStartOfLinkTarget(str: string): boolean { + return !!str.match(/(^|\s)\[.*\]\(\w*/); +} + +function hasStartOfLinkTargetAndNoLinkText(str: string): boolean { return !!str.match(/^[^\[]*\]\([^\)]*$/); } -// function completeListItemPattern(token: marked.Tokens.List): marked.Tokens.List | undefined { -// // Patch up this one list item -// const lastItem = token.items[token.items.length - 1]; +function completeListItemPattern(list: marked.Tokens.List): marked.Tokens.List | undefined { + // Patch up this one list item + const lastListItem = list.items[list.items.length - 1]; + const lastListSubToken = lastListItem.tokens ? lastListItem.tokens[lastListItem.tokens.length - 1] : undefined; + + /* + Example list token structures: + + list + list_item + text + text + codespan + link + list_item + text + code // Complete indented codeblock + list_item + text + space + text + text // Incomplete indented codeblock + list_item + text + list // Nested list + list_item + text + text + + Contrast with paragraph: + paragraph + text + codespan + */ + + let newToken: marked.Token | undefined; + if (lastListSubToken?.type === 'text' && !('inRawBlock' in lastListItem)) { // Why does Tag have a type of 'text' + newToken = completeSingleLinePattern(lastListSubToken as marked.Tokens.Text); + } -// const newList = completeSingleLinePattern(lastItem); -// if (!newList || newList.type !== 'list') { -// // Nothing to fix, or not a pattern we were expecting -// return; -// } + if (!newToken || newToken.type !== 'paragraph') { // 'text' item inside the list item turns into paragraph + // Nothing to fix, or not a pattern we were expecting + return; + } -// // Re-parse the whole list with the last item replaced -// const completeList = marked.lexer(mergeRawTokenText(token.items.slice(0, token.items.length - 1)) + newList.items[0].raw); -// if (completeList.length === 1 && completeList[0].type === 'list') { -// return completeList[0]; -// } + const previousListItemsText = mergeRawTokenText(list.items.slice(0, -1)); -// // Not a pattern we were expecting -// return undefined; -// } + // Grabbing the `- ` off the list item because I can't find a better way to do this + const newListItemText = lastListItem.raw.slice(0, 2) + + mergeRawTokenText(lastListItem.tokens.slice(0, -1)) + + newToken.raw; + + const newList = marked.lexer(previousListItemsText + newListItemText)[0] as marked.Tokens.List; + if (newList.type !== 'list') { + // Something went wrong + return; + } + return newList; +} + +const maxIncompleteTokensFixRounds = 3; export function fillInIncompleteTokens(tokens: marked.TokensList): marked.TokensList { + for (let i = 0; i < maxIncompleteTokensFixRounds; i++) { + const newTokens = fillInIncompleteTokensOnce(tokens); + if (newTokens) { + tokens = newTokens; + } else { + break; + } + } + + return tokens; +} + +function fillInIncompleteTokensOnce(tokens: marked.TokensList): marked.TokensList | null { let i: number; let newTokens: marked.Token[] | undefined; for (i = 0; i < tokens.length; i++) { @@ -666,13 +753,13 @@ export function fillInIncompleteTokens(tokens: marked.TokensList): marked.Tokens break; } - // if (i === tokens.length - 1 && token.type === 'list') { - // const newListToken = completeListItemPattern(token); - // if (newListToken) { - // newTokens = [newListToken]; - // break; - // } - // } + if (i === tokens.length - 1 && token.type === 'list') { + const newListToken = completeListItemPattern(token); + if (newListToken) { + newTokens = [newListToken]; + break; + } + } if (i === tokens.length - 1 && token.type === 'paragraph') { // Only operates on a single token, because any newline that follows this should break these patterns @@ -693,7 +780,7 @@ export function fillInIncompleteTokens(tokens: marked.TokensList): marked.Tokens return newTokensList as marked.TokensList; } - return tokens; + return null; } function completeCodeBlock(tokens: marked.Token[], leader: string): marked.Token[] { diff --git a/src/vs/base/test/browser/markdownRenderer.test.ts b/src/vs/base/test/browser/markdownRenderer.test.ts index 289b3974df837..010c0d672af9f 100644 --- a/src/vs/base/test/browser/markdownRenderer.test.ts +++ b/src/vs/base/test/browser/markdownRenderer.test.ts @@ -362,7 +362,9 @@ suite('MarkdownRenderer', () => { const completeTableTokens = marked.lexer(completeTable); const newTokens = fillInIncompleteTokens(tokens); - ignoreRaw(newTokens, completeTableTokens); + if (newTokens) { + ignoreRaw(newTokens, completeTableTokens); + } assert.deepStrictEqual(newTokens, completeTableTokens); }); @@ -373,7 +375,9 @@ suite('MarkdownRenderer', () => { const newTokens = fillInIncompleteTokens(tokens); - ignoreRaw(newTokens, completeTableTokens); + if (newTokens) { + ignoreRaw(newTokens, completeTableTokens); + } assert.deepStrictEqual(newTokens, completeTableTokens); }); @@ -384,7 +388,9 @@ suite('MarkdownRenderer', () => { const newTokens = fillInIncompleteTokens(tokens); - ignoreRaw(newTokens, completeTableTokens); + if (newTokens) { + ignoreRaw(newTokens, completeTableTokens); + } assert.deepStrictEqual(newTokens, completeTableTokens); }); @@ -592,7 +598,7 @@ const y = 2; assert.deepStrictEqual(newTokens, completeTokens); }); - test.skip(`incomplete ${name} in list`, () => { + test(`incomplete ${name} in list`, () => { const text = `- list item one\n- list item two and ${delimiter}text`; const tokens = marked.lexer(text); const newTokens = fillInIncompleteTokens(tokens); @@ -602,6 +608,83 @@ const y = 2; }); } + suite('list', () => { + test('list with complete codeblock', () => { + const list = `- + \`\`\`js + let x = 1; + \`\`\` +- list item two +`; + const tokens = marked.lexer(list); + const newTokens = fillInIncompleteTokens(tokens); + + assert.deepStrictEqual(newTokens, tokens); + }); + + test.skip('list with incomplete codeblock', () => { + const incomplete = `- list item one + + \`\`\`js + let x = 1;` + const tokens = marked.lexer(incomplete); + const newTokens = fillInIncompleteTokens(tokens); + + const completeTokens = marked.lexer(incomplete + '\n ```'); + assert.deepStrictEqual(newTokens, completeTokens); + }); + + test('list with subitems', () => { + const list = `- hello + - sub item +- text + newline for some reason +` + const tokens = marked.lexer(list); + const newTokens = fillInIncompleteTokens(tokens); + + assert.deepStrictEqual(newTokens, tokens); + }); + + test('list with stuff', () => { + const list = `- list item one \`codespan\` **bold** [link](http://microsoft.com) more text`; + const tokens = marked.lexer(list); + const newTokens = fillInIncompleteTokens(tokens); + + assert.deepStrictEqual(newTokens, tokens); + }); + + test('list with incomplete link text', () => { + const incomplete = `- list item one +- item two [link` + const tokens = marked.lexer(incomplete); + const newTokens = fillInIncompleteTokens(tokens); + + const completeTokens = marked.lexer(incomplete + '](about:blank)'); + assert.deepStrictEqual(newTokens, completeTokens); + }); + + test('list with incomplete link target', () => { + const incomplete = `- list item one +- item two [link](` + const tokens = marked.lexer(incomplete); + const newTokens = fillInIncompleteTokens(tokens); + + const completeTokens = marked.lexer(incomplete + ')'); + assert.deepStrictEqual(newTokens, completeTokens); + }); + + test('list with incomplete link with other stuff', () => { + const incomplete = `- list item one +- item two [\`link` + const tokens = marked.lexer(incomplete); + const newTokens = fillInIncompleteTokens(tokens); + + const completeTokens = marked.lexer(incomplete + '\`](about:blank)'); + assert.deepStrictEqual(newTokens, completeTokens); + }); + }); + suite('codespan', () => { simpleMarkdownTestSuite('codespan', '`'); @@ -720,16 +803,16 @@ const y = 2; assert.deepStrictEqual(newTokens, completeTokens); }); - test('incomplete link target with extra stuff and arg', () => { + test('incomplete link target with extra stuff and incomplete arg', () => { const incomplete = '[before `text` after](http://microsoft.com "more text '; const tokens = marked.lexer(incomplete); const newTokens = fillInIncompleteTokens(tokens); - const completeTokens = marked.lexer(incomplete + ')'); + const completeTokens = marked.lexer(incomplete + '")'); assert.deepStrictEqual(newTokens, completeTokens); }); - test('incomplete link target with arg', () => { + test('incomplete link target with incomplete arg', () => { const incomplete = 'foo [text](http://microsoft.com "more text here '; const tokens = marked.lexer(incomplete); const newTokens = fillInIncompleteTokens(tokens); @@ -738,6 +821,51 @@ const y = 2; assert.deepStrictEqual(newTokens, completeTokens); }); + test('incomplete link target with incomplete arg 2', () => { + const incomplete = '[text](command:_github.copilot.openRelativePath "arg'; + const tokens = marked.lexer(incomplete); + const newTokens = fillInIncompleteTokens(tokens); + + const completeTokens = marked.lexer(incomplete + '")'); + assert.deepStrictEqual(newTokens, completeTokens); + }); + + test('incomplete link target with complete arg', () => { + const incomplete = 'foo [text](http://microsoft.com "more text here"'; + const tokens = marked.lexer(incomplete); + const newTokens = fillInIncompleteTokens(tokens); + + const completeTokens = marked.lexer(incomplete + ')'); + assert.deepStrictEqual(newTokens, completeTokens); + }); + + test('link text with incomplete codespan', () => { + const incomplete = `text [\`codespan`; + const tokens = marked.lexer(incomplete); + const newTokens = fillInIncompleteTokens(tokens); + + const completeTokens = marked.lexer(incomplete + '`](about:blank)'); + assert.deepStrictEqual(newTokens, completeTokens); + }); + + test('link text with incomplete stuff', () => { + const incomplete = `text [more text \`codespan\` text **bold`; + const tokens = marked.lexer(incomplete); + const newTokens = fillInIncompleteTokens(tokens); + + const completeTokens = marked.lexer(incomplete + '**](about:blank)'); + assert.deepStrictEqual(newTokens, completeTokens); + }); + + test('Looks like incomplete link target but isn\'t', () => { + const complete = '**bold** `codespan` text]('; + const tokens = marked.lexer(complete); + const newTokens = fillInIncompleteTokens(tokens); + + const completeTokens = marked.lexer(complete); + assert.deepStrictEqual(newTokens, completeTokens); + }); + test.skip('incomplete link in list', () => { const incomplete = '- [text'; const tokens = marked.lexer(incomplete); From 3df6447dee12de082d36c597c1ce09f23d20e6d2 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 29 Apr 2024 10:37:21 +0200 Subject: [PATCH 071/104] Recently opened: diff editors are not properly excluded when closed (fix #157395) (#211611) --- .../history/browser/historyService.ts | 5 ++-- .../test/browser/historyService.test.ts | 25 ++++++++++++++++--- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/services/history/browser/historyService.ts b/src/vs/workbench/services/history/browser/historyService.ts index 7fde1ff6a00c2..5a232af3d86cc 100644 --- a/src/vs/workbench/services/history/browser/historyService.ts +++ b/src/vs/workbench/services/history/browser/historyService.ts @@ -835,13 +835,14 @@ export class HistoryService extends Disposable implements IHistoryService { // Side-by-side editors get special treatment: we try to distill the // possibly untyped resource inputs from both sides to be able to - // offer these entries from the history to the user still. + // offer these entries from the history to the user still unless + // they are excluded. else { const resourceInputs: IResourceEditorInput[] = []; const sideInputs = editor.primary.matches(editor.secondary) ? [editor.primary] : [editor.primary, editor.secondary]; for (const sideInput of sideInputs) { const candidateResourceInput = this.editorHelper.preferResourceEditorInput(sideInput); - if (isResourceEditorInput(candidateResourceInput)) { + if (isResourceEditorInput(candidateResourceInput) && this.includeInHistory(candidateResourceInput)) { resourceInputs.push(candidateResourceInput); } } diff --git a/src/vs/workbench/services/history/test/browser/historyService.test.ts b/src/vs/workbench/services/history/test/browser/historyService.test.ts index e275f65cef64c..06478095336ca 100644 --- a/src/vs/workbench/services/history/test/browser/historyService.test.ts +++ b/src/vs/workbench/services/history/test/browser/historyService.test.ts @@ -6,7 +6,7 @@ import * as assert from 'assert'; import { ensureNoDisposablesAreLeakedInTestSuite, toResource } from 'vs/base/test/common/utils'; import { URI } from 'vs/base/common/uri'; -import { workbenchInstantiationService, TestFileEditorInput, registerTestEditor, createEditorPart, registerTestFileEditor, TestServiceAccessor, TestTextFileEditor, workbenchTeardown } from 'vs/workbench/test/browser/workbenchTestServices'; +import { workbenchInstantiationService, TestFileEditorInput, registerTestEditor, createEditorPart, registerTestFileEditor, TestServiceAccessor, TestTextFileEditor, workbenchTeardown, registerTestSideBySideEditor } from 'vs/workbench/test/browser/workbenchTestServices'; import { EditorPart } from 'vs/workbench/browser/parts/editor/editorPart'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { IEditorGroupsService, GroupDirection } from 'vs/workbench/services/editor/common/editorGroupsService'; @@ -28,13 +28,14 @@ import { Selection } from 'vs/editor/common/core/selection'; import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane'; import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditorInput'; suite('HistoryService', function () { const TEST_EDITOR_ID = 'MyTestEditorForEditorHistory'; const TEST_EDITOR_INPUT_ID = 'testEditorInputForHistoyService'; - async function createServices(scope = GoScope.DEFAULT): Promise<[EditorPart, HistoryService, EditorService, ITextFileService, IInstantiationService, TestConfigurationService]> { + async function createServices(scope = GoScope.DEFAULT, configureSearchExclude = false): Promise<[EditorPart, HistoryService, EditorService, ITextFileService, IInstantiationService, TestConfigurationService]> { const instantiationService = workbenchInstantiationService(undefined, disposables); const part = await createEditorPart(instantiationService, disposables); @@ -49,6 +50,9 @@ suite('HistoryService', function () { } else if (scope === GoScope.EDITOR) { configurationService.setUserConfiguration('workbench.editor.navigationScope', 'editor'); } + if (configureSearchExclude) { + configurationService.setUserConfiguration('search', { exclude: { "**/node_modules/**": true } }); + } instantiationService.stub(IConfigurationService, configurationService); const historyService = disposables.add(instantiationService.createInstance(HistoryService)); @@ -63,6 +67,7 @@ suite('HistoryService', function () { setup(() => { disposables.add(registerTestEditor(TEST_EDITOR_ID, [new SyncDescriptor(TestFileEditorInput)])); + disposables.add(registerTestSideBySideEditor()); disposables.add(registerTestFileEditor()); }); @@ -660,8 +665,7 @@ suite('HistoryService', function () { } } - const [part, historyService, , , instantiationService, configurationService] = await createServices(); - configurationService.setUserConfiguration('search.exclude', '{ "**/node_modules/**": true }'); + const [part, historyService, editorService, , instantiationService] = await createServices(undefined, true); let history = historyService.getHistory(); assert.strictEqual(history.length, 0); @@ -698,6 +702,19 @@ suite('HistoryService', function () { history = historyService.getHistory(); assert.strictEqual(history.length, 2); + // side by side + const input5 = disposables.add(new TestFileEditorInputWithUntyped(URI.parse('file://bar5'), TEST_EDITOR_INPUT_ID)); + const input6 = disposables.add(new TestFileEditorInputWithUntyped(URI.file('file://bar1/node_modules/test.txt'), TEST_EDITOR_INPUT_ID)); + const input7 = new SideBySideEditorInput(undefined, undefined, input6, input5, editorService); + await part.activeGroup.openEditor(input7, { pinned: true }); + + history = historyService.getHistory(); + assert.strictEqual(history.length, 3); + input7.dispose(); + + history = historyService.getHistory(); + assert.strictEqual(history.length, 3); // only input5 survived, input6 is excluded via search.exclude + return workbenchTeardown(instantiationService); }); From 4e893b209617c8a6fe9672dab52393e0b91bf4da Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 29 Apr 2024 10:37:53 +0200 Subject: [PATCH 072/104] window - always set button height to prevent flicker (#211607) * window - always set button height to prevent flicker * . --- src/vs/platform/window/common/window.ts | 2 ++ src/vs/platform/windows/electron-main/windowImpl.ts | 6 ++++-- src/vs/workbench/browser/parts/titlebar/titlebarPart.ts | 4 ++-- .../electron-sandbox/parts/titlebar/titlebarPart.ts | 4 ++-- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/vs/platform/window/common/window.ts b/src/vs/platform/window/common/window.ts index 2b991c2b2039f..8adf80ad9c78f 100644 --- a/src/vs/platform/window/common/window.ts +++ b/src/vs/platform/window/common/window.ts @@ -221,6 +221,8 @@ export function getTitleBarStyle(configurationService: IConfigurationService): T return isLinux ? TitlebarStyle.NATIVE : TitlebarStyle.CUSTOM; // default to custom on all macOS and Windows } +export const DEFAULT_CUSTOM_TITLEBAR_HEIGHT = 35; // includes space for command center + export function useWindowControlsOverlay(configurationService: IConfigurationService): boolean { if (!isWindows || isWeb) { return false; // only supported on a desktop Windows instance diff --git a/src/vs/platform/windows/electron-main/windowImpl.ts b/src/vs/platform/windows/electron-main/windowImpl.ts index ee03669982cbc..dcb3a1776ecfa 100644 --- a/src/vs/platform/windows/electron-main/windowImpl.ts +++ b/src/vs/platform/windows/electron-main/windowImpl.ts @@ -32,7 +32,7 @@ import { IApplicationStorageMainService, IStorageMainService } from 'vs/platform import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { ThemeIcon } from 'vs/base/common/themables'; import { IThemeMainService } from 'vs/platform/theme/electron-main/themeMainService'; -import { getMenuBarVisibility, IFolderToOpen, INativeWindowConfiguration, IWindowSettings, IWorkspaceToOpen, MenuBarVisibility, hasNativeTitlebar, useNativeFullScreen, useWindowControlsOverlay } from 'vs/platform/window/common/window'; +import { getMenuBarVisibility, IFolderToOpen, INativeWindowConfiguration, IWindowSettings, IWorkspaceToOpen, MenuBarVisibility, hasNativeTitlebar, useNativeFullScreen, useWindowControlsOverlay, DEFAULT_CUSTOM_TITLEBAR_HEIGHT } from 'vs/platform/window/common/window'; import { defaultBrowserWindowOptions, IWindowsMainService, OpenContext, WindowStateValidator } from 'vs/platform/windows/electron-main/windows'; import { ISingleFolderWorkspaceIdentifier, IWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, isWorkspaceIdentifier, toWorkspaceIdentifier } from 'vs/platform/workspace/common/workspace'; import { IWorkspacesManagementMainService } from 'vs/platform/workspaces/electron-main/workspacesManagementMainService'; @@ -136,11 +136,13 @@ export abstract class BaseWindow extends Disposable implements IBaseWindow { win.setSheetOffset(isBigSurOrNewer(release()) ? 28 : 22); // offset dialogs by the height of the custom title bar if we have any } - // Update the window controls immediately based on cached values + // Update the window controls immediately based on cached or default values if (useCustomTitleStyle && ((isWindows && useWindowControlsOverlay(this.configurationService)) || isMacintosh)) { const cachedWindowControlHeight = this.stateService.getItem((BaseWindow.windowControlHeightStateStorageKey)); if (cachedWindowControlHeight) { this.updateWindowControls({ height: cachedWindowControlHeight }); + } else { + this.updateWindowControls({ height: DEFAULT_CUSTOM_TITLEBAR_HEIGHT }); } } diff --git a/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts b/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts index 5c2ff6882c44b..0bee377dce951 100644 --- a/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts +++ b/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts @@ -8,7 +8,7 @@ import { localize, localize2 } from 'vs/nls'; import { MultiWindowParts, Part } from 'vs/workbench/browser/part'; import { ITitleService } from 'vs/workbench/services/title/browser/titleService'; import { getZoomFactor, isWCOEnabled } from 'vs/base/browser/browser'; -import { MenuBarVisibility, getTitleBarStyle, getMenuBarVisibility, TitlebarStyle, hasCustomTitlebar, hasNativeTitlebar } from 'vs/platform/window/common/window'; +import { MenuBarVisibility, getTitleBarStyle, getMenuBarVisibility, TitlebarStyle, hasCustomTitlebar, hasNativeTitlebar, DEFAULT_CUSTOM_TITLEBAR_HEIGHT } from 'vs/platform/window/common/window'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; import { IConfigurationService, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration'; @@ -200,7 +200,7 @@ export class BrowserTitlebarPart extends Part implements ITitlebarPart { readonly maximumWidth: number = Number.POSITIVE_INFINITY; get minimumHeight(): number { - const value = this.isCommandCenterVisible || (isWeb && isWCOEnabled()) ? 35 : 30; + const value = this.isCommandCenterVisible || (isWeb && isWCOEnabled()) ? DEFAULT_CUSTOM_TITLEBAR_HEIGHT : 30; return value / (this.preventZoom ? getZoomFactor(getWindow(this.element)) : 1); } diff --git a/src/vs/workbench/electron-sandbox/parts/titlebar/titlebarPart.ts b/src/vs/workbench/electron-sandbox/parts/titlebar/titlebarPart.ts index 4e4e8f5b7d0e2..12609c51916d1 100644 --- a/src/vs/workbench/electron-sandbox/parts/titlebar/titlebarPart.ts +++ b/src/vs/workbench/electron-sandbox/parts/titlebar/titlebarPart.ts @@ -18,7 +18,7 @@ import { IContextMenuService } from 'vs/platform/contextview/browser/contextView import { IThemeService } from 'vs/platform/theme/common/themeService'; import { IWorkbenchLayoutService, Parts } from 'vs/workbench/services/layout/browser/layoutService'; import { INativeHostService } from 'vs/platform/native/common/native'; -import { hasNativeTitlebar, useWindowControlsOverlay } from 'vs/platform/window/common/window'; +import { hasNativeTitlebar, useWindowControlsOverlay, DEFAULT_CUSTOM_TITLEBAR_HEIGHT } from 'vs/platform/window/common/window'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { Codicon } from 'vs/base/common/codicons'; import { ThemeIcon } from 'vs/base/common/themables'; @@ -37,7 +37,7 @@ export class NativeTitlebarPart extends BrowserTitlebarPart { return super.minimumHeight; } - return (this.isCommandCenterVisible ? 35 : this.macTitlebarSize) / (this.preventZoom ? getZoomFactor(getWindow(this.element)) : 1); + return (this.isCommandCenterVisible ? DEFAULT_CUSTOM_TITLEBAR_HEIGHT : this.macTitlebarSize) / (this.preventZoom ? getZoomFactor(getWindow(this.element)) : 1); } override get maximumHeight(): number { return this.minimumHeight; } From 2ad9cb5b88054a6713ffc6e27573a79b1d637583 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 29 Apr 2024 10:40:04 +0200 Subject: [PATCH 073/104] Empty space behind activity bar (fix #209535) (#211608) --- src/vs/workbench/browser/layout.ts | 7 ++----- .../parts/auxiliarybar/auxiliaryBarPart.ts | 3 ++- .../browser/parts/sidebar/sidebarPart.ts | 18 ++++++++++-------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/vs/workbench/browser/layout.ts b/src/vs/workbench/browser/layout.ts index 94ec1087453c1..0263c12e2daff 100644 --- a/src/vs/workbench/browser/layout.ts +++ b/src/vs/workbench/browser/layout.ts @@ -1673,7 +1673,6 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi private setActivityBarHidden(hidden: boolean, skipLayout?: boolean): void { this.stateModel.setRuntimeValue(LayoutStateKeys.ACTIVITYBAR_HIDDEN, hidden); - // Propagate to grid this.workbenchGrid.setViewVisible(this.activityBarPartView, !hidden); } @@ -2565,13 +2564,11 @@ class LayoutStateModel extends Disposable { } private updateStateFromLegacySettings(configurationChangeEvent: IConfigurationChangeEvent): void { - const isZenMode = this.getRuntimeValue(LayoutStateKeys.ZEN_MODE_ACTIVE); - - if (configurationChangeEvent.affectsConfiguration(LayoutSettings.ACTIVITY_BAR_LOCATION) && !isZenMode) { + if (configurationChangeEvent.affectsConfiguration(LayoutSettings.ACTIVITY_BAR_LOCATION)) { this.setRuntimeValueAndFire(LayoutStateKeys.ACTIVITYBAR_HIDDEN, this.isActivityBarHidden()); } - if (configurationChangeEvent.affectsConfiguration(LegacyWorkbenchLayoutSettings.STATUSBAR_VISIBLE) && !isZenMode) { + if (configurationChangeEvent.affectsConfiguration(LegacyWorkbenchLayoutSettings.STATUSBAR_VISIBLE)) { this.setRuntimeValueAndFire(LayoutStateKeys.STATUSBAR_HIDDEN, !this.configurationService.getValue(LegacyWorkbenchLayoutSettings.STATUSBAR_VISIBLE)); } diff --git a/src/vs/workbench/browser/parts/auxiliarybar/auxiliaryBarPart.ts b/src/vs/workbench/browser/parts/auxiliarybar/auxiliaryBarPart.ts index 4cbc1def33568..16c40e836f214 100644 --- a/src/vs/workbench/browser/parts/auxiliarybar/auxiliaryBarPart.ts +++ b/src/vs/workbench/browser/parts/auxiliarybar/auxiliaryBarPart.ts @@ -71,7 +71,7 @@ export class AuxiliaryBarPart extends AbstractPaneCompositePart { return Math.max(width, 300); } - readonly priority: LayoutPriority = LayoutPriority.Low; + readonly priority = LayoutPriority.Low; constructor( @INotificationService notificationService: INotificationService, @@ -245,6 +245,7 @@ export class AuxiliaryBarPart extends AbstractPaneCompositePart { if (this.getCompositeBarPosition() === CompositeBarPosition.TOP) { return 22; } + return super.getToolbarWidth(); } diff --git a/src/vs/workbench/browser/parts/sidebar/sidebarPart.ts b/src/vs/workbench/browser/parts/sidebar/sidebarPart.ts index 4ce6293ee2be9..1710df58d23ba 100644 --- a/src/vs/workbench/browser/parts/sidebar/sidebarPart.ts +++ b/src/vs/workbench/browser/parts/sidebar/sidebarPart.ts @@ -62,7 +62,7 @@ export class SidebarPart extends AbstractPaneCompositePart { return Math.max(width, 300); } - private readonly acitivityBarPart: ActivitybarPart; + private readonly activityBarPart = this._register(this.instantiationService.createInstance(ActivitybarPart, this)); //#endregion @@ -104,7 +104,6 @@ export class SidebarPart extends AbstractPaneCompositePart { menuService, ); - this.acitivityBarPart = this._register(instantiationService.createInstance(ActivitybarPart, this)); this.rememberActivityBarVisiblePosition(); this._register(configurationService.onDidChangeConfiguration(e => { if (e.affectsConfiguration(LayoutSettings.ACTIVITY_BAR_LOCATION)) { @@ -116,7 +115,7 @@ export class SidebarPart extends AbstractPaneCompositePart { } private onDidChangeActivityBarLocation(): void { - this.acitivityBarPart.hide(); + this.activityBarPart.hide(); this.updateCompositeBar(); @@ -126,7 +125,7 @@ export class SidebarPart extends AbstractPaneCompositePart { } if (this.shouldShowActivityBar()) { - this.acitivityBarPart.show(); + this.activityBarPart.show(); } this.rememberActivityBarVisiblePosition(); @@ -135,7 +134,6 @@ export class SidebarPart extends AbstractPaneCompositePart { override updateStyles(): void { super.updateStyles(); - // Part container const container = assertIsDefined(this.getContainer()); container.style.backgroundColor = this.getColor(SIDE_BAR_BACKGROUND) || ''; @@ -213,6 +211,7 @@ export class SidebarPart extends AbstractPaneCompositePart { if (this.shouldShowCompositeBar()) { return false; } + return this.configurationService.getValue(LayoutSettings.ACTIVITY_BAR_LOCATION) !== ActivityBarPosition.HIDDEN; } @@ -244,25 +243,28 @@ export class SidebarPart extends AbstractPaneCompositePart { } override getPinnedPaneCompositeIds(): string[] { - return this.shouldShowCompositeBar() ? super.getPinnedPaneCompositeIds() : this.acitivityBarPart.getPinnedPaneCompositeIds(); + return this.shouldShowCompositeBar() ? super.getPinnedPaneCompositeIds() : this.activityBarPart.getPinnedPaneCompositeIds(); } override getVisiblePaneCompositeIds(): string[] { - return this.shouldShowCompositeBar() ? super.getVisiblePaneCompositeIds() : this.acitivityBarPart.getVisiblePaneCompositeIds(); + return this.shouldShowCompositeBar() ? super.getVisiblePaneCompositeIds() : this.activityBarPart.getVisiblePaneCompositeIds(); } async focusActivityBar(): Promise { if (this.configurationService.getValue(LayoutSettings.ACTIVITY_BAR_LOCATION) === ActivityBarPosition.HIDDEN) { await this.configurationService.updateValue(LayoutSettings.ACTIVITY_BAR_LOCATION, this.getRememberedActivityBarVisiblePosition()); + this.onDidChangeActivityBarLocation(); } + if (this.shouldShowCompositeBar()) { this.focusComositeBar(); } else { if (!this.layoutService.isVisible(Parts.ACTIVITYBAR_PART)) { this.layoutService.setPartHidden(false, Parts.ACTIVITYBAR_PART); } - this.acitivityBarPart.show(true); + + this.activityBarPart.show(true); } } From 1d05283bcad67a18caa6f35b70190e09df761e63 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 29 Apr 2024 10:49:32 +0200 Subject: [PATCH 074/104] Pressing F6 on Windows doesn't navigate to the secondary side bar (fix #171229) (#211617) --- src/vs/workbench/browser/actions/navigationActions.ts | 9 +++++++-- src/vs/workbench/browser/layout.ts | 4 ++++ src/vs/workbench/browser/parts/paneCompositePart.ts | 2 +- src/vs/workbench/browser/parts/sidebar/sidebarPart.ts | 2 +- 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/browser/actions/navigationActions.ts b/src/vs/workbench/browser/actions/navigationActions.ts index e0e838c85bfd3..56b88fe52d6e6 100644 --- a/src/vs/workbench/browser/actions/navigationActions.ts +++ b/src/vs/workbench/browser/actions/navigationActions.ts @@ -273,10 +273,13 @@ abstract class BaseFocusAction extends Action2 { neighbour = next ? Parts.PANEL_PART : Parts.SIDEBAR_PART; break; case Parts.PANEL_PART: - neighbour = next ? Parts.STATUSBAR_PART : Parts.EDITOR_PART; + neighbour = next ? Parts.AUXILIARYBAR_PART : Parts.EDITOR_PART; + break; + case Parts.AUXILIARYBAR_PART: + neighbour = next ? Parts.STATUSBAR_PART : Parts.PANEL_PART; break; case Parts.STATUSBAR_PART: - neighbour = next ? Parts.ACTIVITYBAR_PART : Parts.PANEL_PART; + neighbour = next ? Parts.ACTIVITYBAR_PART : Parts.AUXILIARYBAR_PART; break; case Parts.ACTIVITYBAR_PART: neighbour = next ? Parts.SIDEBAR_PART : Parts.STATUSBAR_PART; @@ -306,6 +309,8 @@ abstract class BaseFocusAction extends Action2 { currentlyFocusedPart = Parts.STATUSBAR_PART; } else if (layoutService.hasFocus(Parts.SIDEBAR_PART)) { currentlyFocusedPart = Parts.SIDEBAR_PART; + } else if (layoutService.hasFocus(Parts.AUXILIARYBAR_PART)) { + currentlyFocusedPart = Parts.AUXILIARYBAR_PART; } else if (layoutService.hasFocus(Parts.PANEL_PART)) { currentlyFocusedPart = Parts.PANEL_PART; } diff --git a/src/vs/workbench/browser/layout.ts b/src/vs/workbench/browser/layout.ts index 0263c12e2daff..864da4c7f8c86 100644 --- a/src/vs/workbench/browser/layout.ts +++ b/src/vs/workbench/browser/layout.ts @@ -1148,6 +1148,10 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi this.paneCompositeService.getActivePaneComposite(ViewContainerLocation.Sidebar)?.focus(); break; } + case Parts.AUXILIARYBAR_PART: { + this.paneCompositeService.getActivePaneComposite(ViewContainerLocation.AuxiliaryBar)?.focus(); + break; + } case Parts.ACTIVITYBAR_PART: (this.getPart(Parts.SIDEBAR_PART) as SidebarPart).focusActivityBar(); break; diff --git a/src/vs/workbench/browser/parts/paneCompositePart.ts b/src/vs/workbench/browser/parts/paneCompositePart.ts index e7f574aca2492..68e797d69e125 100644 --- a/src/vs/workbench/browser/parts/paneCompositePart.ts +++ b/src/vs/workbench/browser/parts/paneCompositePart.ts @@ -526,7 +526,7 @@ export abstract class AbstractPaneCompositePart extends CompositePart Date: Mon, 29 Apr 2024 11:33:29 +0200 Subject: [PATCH 075/104] Activity bar does not support `contrastActiveBorder` (fix #167005) (#211624) --- .../parts/activitybar/activitybarPart.ts | 1 + .../activitybar/media/activityaction.css | 22 +------------------ src/vs/workbench/common/theme.ts | 2 +- 3 files changed, 3 insertions(+), 22 deletions(-) diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index 15e58a5817990..a3fc3c07785f9 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -617,6 +617,7 @@ registerThemingParticipant((theme, collector) => { .monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item:before { content: ""; position: absolute; + display: block; top: 8px; left: 8px; height: 32px; diff --git a/src/vs/workbench/browser/parts/activitybar/media/activityaction.css b/src/vs/workbench/browser/parts/activitybar/media/activityaction.css index a47bbe794a0f4..f42d3307fb75d 100644 --- a/src/vs/workbench/browser/parts/activitybar/media/activityaction.css +++ b/src/vs/workbench/browser/parts/activitybar/media/activityaction.css @@ -26,26 +26,6 @@ display: block; } -.monaco-workbench .activitybar > .content > .composite-bar > .monaco-action-bar .action-item::before { - top: 1px; - margin-top: -2px; -} - -.monaco-workbench .activitybar > .content > .composite-bar > .monaco-action-bar .action-item::after { - bottom: 1px; - margin-bottom: -2px; -} - -.monaco-workbench .activitybar > .content > .composite-bar > .monaco-action-bar .action-item:first-of-type::before { - top: 2px; - margin-top: -2px; -} - -.monaco-workbench .activitybar > .content > .composite-bar > .monaco-action-bar .action-item:last-of-type::after { - bottom: 2px; - margin-bottom: -2px; -} - .monaco-workbench .activitybar > .content > .composite-bar > .monaco-action-bar .action-item.top::before, .monaco-workbench .activitybar > .content > .composite-bar > .monaco-action-bar .action-item.top::after, .monaco-workbench .activitybar > .content > .composite-bar > .monaco-action-bar .action-item.bottom::before, @@ -109,7 +89,7 @@ .monaco-workbench.hc-black .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.checked .active-item-indicator:before, .monaco-workbench.hc-black .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item:focus .active-item-indicator:before { - border-color: var(--vscode-focusBorder); + border-color: var(--vscode-activityBar-activeBorder); } .monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.checked .active-item-indicator:before { diff --git a/src/vs/workbench/common/theme.ts b/src/vs/workbench/common/theme.ts index 9a0f4dda2c576..b6a90af346973 100644 --- a/src/vs/workbench/common/theme.ts +++ b/src/vs/workbench/common/theme.ts @@ -677,7 +677,7 @@ export const ACTIVITY_BAR_BORDER = registerColor('activityBar.border', { export const ACTIVITY_BAR_ACTIVE_BORDER = registerColor('activityBar.activeBorder', { dark: ACTIVITY_BAR_FOREGROUND, light: ACTIVITY_BAR_FOREGROUND, - hcDark: null, + hcDark: contrastBorder, hcLight: contrastBorder }, localize('activityBarActiveBorder', "Activity bar border color for the active item. The activity bar is showing on the far left or right and allows to switch between views of the side bar.")); From e1a8b9a1e380130db9facc5a58a0e3bce8968f5b Mon Sep 17 00:00:00 2001 From: Wenfang Du Date: Mon, 29 Apr 2024 17:35:02 +0800 Subject: [PATCH 076/104] Add 'git-rebase-todo' to COMMON_FILES_FILTER in WorkspacesHistoryMainService (#211614) --- .../workspaces/electron-main/workspacesHistoryMainService.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vs/platform/workspaces/electron-main/workspacesHistoryMainService.ts b/src/vs/platform/workspaces/electron-main/workspacesHistoryMainService.ts index 25a017e19a95f..a6f7fc430bcdd 100644 --- a/src/vs/platform/workspaces/electron-main/workspacesHistoryMainService.ts +++ b/src/vs/platform/workspaces/electron-main/workspacesHistoryMainService.ts @@ -300,7 +300,8 @@ export class WorkspacesHistoryMainService extends Disposable implements IWorkspa // Exclude some very common files from the dock/taskbar private static readonly COMMON_FILES_FILTER = [ 'COMMIT_EDITMSG', - 'MERGE_MSG' + 'MERGE_MSG', + 'git-rebase-todo' ]; private readonly macOSRecentDocumentsUpdater = this._register(new ThrottledDelayer(800)); From 6074d1811bdd998b8d2b69e5063b3a6be662235d Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 29 Apr 2024 11:39:25 +0200 Subject: [PATCH 077/104] sqlite - block `flush` when closed (fix #211270) (#211620) --- src/vs/base/parts/storage/common/storage.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/vs/base/parts/storage/common/storage.ts b/src/vs/base/parts/storage/common/storage.ts index eb9607e6c3e6a..a1afb1f23ea83 100644 --- a/src/vs/base/parts/storage/common/storage.ts +++ b/src/vs/base/parts/storage/common/storage.ts @@ -384,8 +384,11 @@ export class Storage extends Disposable implements IStorage { } async flush(delay?: number): Promise { - if (!this.hasPending) { - return; // return early if nothing to do + if ( + this.state === StorageState.Closed || // Return early if we are already closed + this.pendingClose // return early if nothing to do + ) { + return; } return this.doFlush(delay); From 3ce352c9fa9009226cebe658bdf91e0a05d9e339 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Mon, 29 Apr 2024 02:51:37 -0700 Subject: [PATCH 078/104] More more terminal suggest code into terminalContrib --- src/vs/platform/terminal/common/terminal.ts | 6 -- .../terminal/browser/terminal.contribution.ts | 7 +-- .../contrib/terminal/browser/terminal.ts | 10 ---- .../browser/terminalProcessManager.ts | 8 ++- .../contrib/terminal/common/terminal.ts | 14 +---- .../terminal/common/terminalConfiguration.ts | 29 +-------- .../browser/terminal.suggest.contribution.ts | 60 +++++++++++++++---- .../suggest/browser/terminalSuggestAddon.ts | 15 ++++- .../suggest/common/terminal.suggest.ts | 22 +++++++ .../common/terminalSuggestConfiguration.ts | 48 +++++++++++++++ 10 files changed, 141 insertions(+), 78 deletions(-) create mode 100644 src/vs/workbench/contrib/terminalContrib/suggest/common/terminal.suggest.ts create mode 100644 src/vs/workbench/contrib/terminalContrib/suggest/common/terminalSuggestConfiguration.ts diff --git a/src/vs/platform/terminal/common/terminal.ts b/src/vs/platform/terminal/common/terminal.ts index 85043f448e9f1..f8e502eb9086f 100644 --- a/src/vs/platform/terminal/common/terminal.ts +++ b/src/vs/platform/terminal/common/terminal.ts @@ -116,12 +116,6 @@ export const enum TerminalSettingId { IgnoreBracketedPasteMode = 'terminal.integrated.ignoreBracketedPasteMode', FocusAfterRun = 'terminal.integrated.focusAfterRun', - // terminal.suggest.contribution - SuggestEnabled = 'terminal.integrated.suggest.enabled', - SuggestEnabledLegacy = 'terminal.integrated.shellIntegration.suggestEnabled', - SuggestQuickSuggestions = 'terminal.integrated.suggest.quickSuggestions', - SuggestOnTriggerCharacters = 'terminal.integrated.suggest.suggestOnTriggerCharacters', - // Debug settings that are hidden from user /** Simulated latency applied to all calls made to the pty host */ diff --git a/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts b/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts index 1a2444f223908..84953ef53b0e6 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts @@ -22,7 +22,7 @@ import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/ import { IKeybindings, KeybindingWeight, KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { IQuickAccessRegistry, Extensions as QuickAccessExtensions } from 'vs/platform/quickinput/common/quickAccess'; import { Registry } from 'vs/platform/registry/common/platform'; -import { ITerminalLogService, TerminalSettingId, WindowsShellType } from 'vs/platform/terminal/common/terminal'; +import { ITerminalLogService, WindowsShellType } from 'vs/platform/terminal/common/terminal'; import { TerminalLogService } from 'vs/platform/terminal/common/terminalLogService'; import { registerTerminalPlatformConfiguration } from 'vs/platform/terminal/common/terminalPlatformConfiguration'; import { EditorPaneDescriptor, IEditorPaneRegistry } from 'vs/workbench/browser/editor'; @@ -205,11 +205,6 @@ registerSendSequenceKeybinding('\x1b[24~d', { // F12,d -> shift+end (SelectLine) when: ContextKeyExpr.and(TerminalContextKeys.focus, ContextKeyExpr.equals(TerminalContextKeyStrings.ShellType, WindowsShellType.PowerShell), TerminalContextKeys.terminalShellIntegrationEnabled, CONTEXT_ACCESSIBILITY_MODE_ENABLED.negate()), mac: { primary: KeyMod.Shift | KeyMod.CtrlCmd | KeyCode.RightArrow } }); -registerSendSequenceKeybinding('\x1b[24~e', { // F12,e -> ctrl+space (Native suggest) - when: ContextKeyExpr.and(TerminalContextKeys.focus, ContextKeyExpr.equals(TerminalContextKeyStrings.ShellType, WindowsShellType.PowerShell), TerminalContextKeys.terminalShellIntegrationEnabled, CONTEXT_ACCESSIBILITY_MODE_ENABLED.negate(), ContextKeyExpr.or(ContextKeyExpr.equals(`config.${TerminalSettingId.SuggestEnabled}`, true), ContextKeyExpr.equals(`config.${TerminalSettingId.SuggestEnabledLegacy}`, true))), - primary: KeyMod.CtrlCmd | KeyCode.Space, - mac: { primary: KeyMod.WinCtrl | KeyCode.Space } -}); // Always on pwsh keybindings registerSendSequenceKeybinding('\x1b[1;2H', { // Shift+home diff --git a/src/vs/workbench/contrib/terminal/browser/terminal.ts b/src/vs/workbench/contrib/terminal/browser/terminal.ts index 8fdc2d6c5dee4..77d22d4aaf36a 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminal.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminal.ts @@ -22,7 +22,6 @@ import { IEditableData } from 'vs/workbench/common/views'; import { ITerminalStatusList } from 'vs/workbench/contrib/terminal/browser/terminalStatusList'; import { XtermTerminal } from 'vs/workbench/contrib/terminal/browser/xterm/xtermTerminal'; import { IRegisterContributedProfileArgs, IRemoteTerminalAttachTarget, IStartExtensionTerminalRequest, ITerminalConfiguration, ITerminalFont, ITerminalProcessExtHostProxy, ITerminalProcessInfo } from 'vs/workbench/contrib/terminal/common/terminal'; -import { ISimpleSelectedSuggestion } from 'vs/workbench/services/suggest/browser/simpleSuggestWidget'; import type { IMarker, ITheme, Terminal as RawXtermTerminal, IBufferRange } from '@xterm/xterm'; import { ScrollPosition } from 'vs/workbench/contrib/terminal/browser/xterm/markNavigationAddon'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; @@ -1239,12 +1238,3 @@ export const enum LinuxDistro { export const enum TerminalDataTransfers { Terminals = 'Terminals' } - -export interface ISuggestController { - selectPreviousSuggestion(): void; - selectPreviousPageSuggestion(): void; - selectNextSuggestion(): void; - selectNextPageSuggestion(): void; - acceptSelectedSuggestion(suggestion?: Pick): void; - hideSuggestWidget(): void; -} diff --git a/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts b/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts index 3bb3f632c0721..01db326f019be 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts @@ -42,6 +42,10 @@ import { getActiveWindow, runWhenWindowIdle } from 'vs/base/browser/dom'; import { mainWindow } from 'vs/base/browser/window'; import { shouldUseEnvironmentVariableCollection } from 'vs/platform/terminal/common/terminalEnvironment'; +// HACK: This file should not depend on terminalContrib +// eslint-disable-next-line local/code-import-patterns +import { TerminalSuggestSettingId } from 'vs/workbench/contrib/terminalContrib/suggest/common/terminalSuggestConfiguration'; + const enum ProcessConstants { /** * The amount of time to consider terminal errors to be related to the launch. @@ -285,7 +289,7 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce const options: ITerminalProcessOptions = { shellIntegration: { enabled: this._configurationService.getValue(TerminalSettingId.ShellIntegrationEnabled), - suggestEnabled: this._configurationService.getValue(TerminalSettingId.SuggestEnabled) || this._configurationService.getValue(TerminalSettingId.SuggestEnabledLegacy), + suggestEnabled: this._configurationService.getValue(TerminalSuggestSettingId.Enabled) || this._configurationService.getValue(TerminalSuggestSettingId.EnabledLegacy), nonce: this.shellIntegrationNonce }, windowsEnableConpty: this._terminalConfigurationService.config.windowsEnableConpty, @@ -485,7 +489,7 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce const options: ITerminalProcessOptions = { shellIntegration: { enabled: this._configurationService.getValue(TerminalSettingId.ShellIntegrationEnabled), - suggestEnabled: this._configurationService.getValue(TerminalSettingId.SuggestEnabled) || this._configurationService.getValue(TerminalSettingId.SuggestEnabledLegacy), + suggestEnabled: this._configurationService.getValue(TerminalSuggestSettingId.Enabled) || this._configurationService.getValue(TerminalSuggestSettingId.EnabledLegacy), nonce: this.shellIntegrationNonce }, windowsEnableConpty: this._terminalConfigurationService.config.windowsEnableConpty, diff --git a/src/vs/workbench/contrib/terminal/common/terminal.ts b/src/vs/workbench/contrib/terminal/common/terminal.ts index c6a888ed74f2c..ce92a42e1b779 100644 --- a/src/vs/workbench/contrib/terminal/common/terminal.ts +++ b/src/vs/workbench/contrib/terminal/common/terminal.ts @@ -23,6 +23,7 @@ import { IExtensionPointDescriptor } from 'vs/workbench/services/extensions/comm // since they need to be included in the terminal module import { defaultTerminalAccessibilityCommandsToSkipShell } from 'vs/workbench/contrib/terminalContrib/accessibility/common/terminal.accessibility'; // eslint-disable-line local/code-import-patterns import { defaultTerminalFindCommandToSkipShell } from 'vs/workbench/contrib/terminalContrib/find/common/terminal.find'; // eslint-disable-line local/code-import-patterns +import { defaultTerminalSuggestCommandsToSkipShell } from 'vs/workbench/contrib/terminalContrib/suggest/common/terminal.suggest'; // eslint-disable-line local/code-import-patterns export const TERMINAL_VIEW_ID = 'terminal'; @@ -477,12 +478,6 @@ export const enum TerminalCommandId { MoveIntoNewWindow = 'workbench.action.terminal.moveIntoNewWindow', SetDimensions = 'workbench.action.terminal.setDimensions', ClearPreviousSessionHistory = 'workbench.action.terminal.clearPreviousSessionHistory', - SelectPrevSuggestion = 'workbench.action.terminal.selectPrevSuggestion', - SelectPrevPageSuggestion = 'workbench.action.terminal.selectPrevPageSuggestion', - SelectNextSuggestion = 'workbench.action.terminal.selectNextSuggestion', - SelectNextPageSuggestion = 'workbench.action.terminal.selectNextPageSuggestion', - AcceptSelectedSuggestion = 'workbench.action.terminal.acceptSelectedSuggestion', - HideSuggestWidget = 'workbench.action.terminal.hideSuggestWidget', FocusHover = 'workbench.action.terminal.focusHover', ShowEnvironmentContributions = 'workbench.action.terminal.showEnvironmentContributions', StartVoice = 'workbench.action.terminal.startVoice', @@ -542,12 +537,6 @@ export const DEFAULT_COMMANDS_TO_SKIP_SHELL: string[] = [ TerminalCommandId.SplitInActiveWorkspace, TerminalCommandId.Split, TerminalCommandId.Toggle, - TerminalCommandId.SelectPrevSuggestion, - TerminalCommandId.SelectPrevPageSuggestion, - TerminalCommandId.SelectNextSuggestion, - TerminalCommandId.SelectNextPageSuggestion, - TerminalCommandId.AcceptSelectedSuggestion, - TerminalCommandId.HideSuggestWidget, TerminalCommandId.FocusHover, AccessibilityCommandId.OpenAccessibilityHelp, 'editor.action.toggleTabFocusMode', @@ -636,6 +625,7 @@ export const DEFAULT_COMMANDS_TO_SKIP_SHELL: string[] = [ 'workbench.action.terminal.chat.viewInChat', ...defaultTerminalAccessibilityCommandsToSkipShell, ...defaultTerminalFindCommandToSkipShell, + ...defaultTerminalSuggestCommandsToSkipShell, ]; export const terminalContributionsDescriptor: IExtensionPointDescriptor = { diff --git a/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts b/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts index 9b1422eb16d84..3ccbefd5c2d0d 100644 --- a/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts +++ b/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts @@ -20,6 +20,7 @@ import { terminalAccessibilityConfiguration } from 'vs/workbench/contrib/termina import { terminalStickyScrollConfiguration } from 'vs/workbench/contrib/terminalContrib/stickyScroll/common/terminalStickyScrollConfiguration'; // eslint-disable-line local/code-import-patterns import { terminalTypeAheadConfiguration } from 'vs/workbench/contrib/terminalContrib/typeAhead/common/terminalTypeAheadConfiguration'; // eslint-disable-line local/code-import-patterns import { terminalZoomConfiguration } from 'vs/workbench/contrib/terminalContrib/zoom/common/terminal.zoom'; // eslint-disable-line local/code-import-patterns +import { terminalSuggestConfiguration } from 'vs/workbench/contrib/terminalContrib/suggest/common/terminalSuggestConfiguration'; // eslint-disable-line local/code-import-patterns const terminalDescriptors = '\n- ' + [ '`\${cwd}`: ' + localize("cwd", "the terminal's current working directory"), @@ -623,35 +624,9 @@ const terminalConfiguration: IConfigurationNode = { }, ...terminalAccessibilityConfiguration, ...terminalStickyScrollConfiguration, + ...terminalSuggestConfiguration, ...terminalTypeAheadConfiguration, ...terminalZoomConfiguration, - - // terminal.suggest.contribution - [TerminalSettingId.SuggestEnabled]: { - restricted: true, - markdownDescription: localize('suggest.enabled', "Enables experimental terminal Intellisense suggestions for supported shells ({0}) when {1} is set to {2}.\n\nIf shell integration is installed manually, {3} needs to be set to {4} before calling the shell integration script.", 'PowerShell', `\`#${TerminalSettingId.ShellIntegrationEnabled}#\``, '`true`', '`VSCODE_SUGGEST`', '`1`'), - type: 'boolean', - default: false, - }, - [TerminalSettingId.SuggestEnabledLegacy]: { - restricted: true, - markdownDescription: localize('suggest.enabled', "Enables experimental terminal Intellisense suggestions for supported shells ({0}) when {1} is set to {2}.\n\nIf shell integration is installed manually, {3} needs to be set to {4} before calling the shell integration script.", 'PowerShell', `\`#${TerminalSettingId.ShellIntegrationEnabled}#\``, '`true`', '`VSCODE_SUGGEST`', '`1`'), - type: 'boolean', - default: false, - markdownDeprecationMessage: localize('suggest.enabled.deprecated', 'This setting is deprecated, please use `{0}` instead.', `\`#${TerminalSettingId.SuggestEnabled}#\``) - }, - [TerminalSettingId.SuggestQuickSuggestions]: { - restricted: true, - markdownDescription: localize('suggest.quickSuggestions', "Controls whether suggestions should automatically show up while typing. Also be aware of the {0}-setting which controls if suggestions are triggered by special characters.", `\`#${TerminalSettingId.SuggestOnTriggerCharacters}#\``), - type: 'boolean', - default: true, - }, - [TerminalSettingId.SuggestOnTriggerCharacters]: { - restricted: true, - markdownDescription: localize('suggest.suggestOnTriggerCharacters', "Controls whether suggestions should automatically show up when typing trigger characters."), - type: 'boolean', - default: true, - }, } }; diff --git a/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminal.suggest.contribution.ts b/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminal.suggest.contribution.ts index 512373ba4a296..fe1a317de539e 100644 --- a/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminal.suggest.contribution.ts +++ b/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminal.suggest.contribution.ts @@ -12,14 +12,19 @@ import { TerminalWidgetManager } from 'vs/workbench/contrib/terminal/browser/wid import { SuggestAddon } from 'vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon'; import { ITerminalConfiguration, ITerminalProcessManager, TERMINAL_CONFIG_SECTION, TerminalCommandId } from 'vs/workbench/contrib/terminal/common/terminal'; import type { Terminal as RawXtermTerminal } from '@xterm/xterm'; -import { ContextKeyExpr, IContextKey, IContextKeyService, IReadableSet } from 'vs/platform/contextkey/common/contextkey'; -import { TerminalContextKeys } from 'vs/workbench/contrib/terminal/common/terminalContextKey'; -import { registerActiveInstanceAction } from 'vs/workbench/contrib/terminal/browser/terminalActions'; +import { ContextKeyExpr, IContextKey, IContextKeyService, IReadableSet, type ContextKeyExpression } from 'vs/platform/contextkey/common/contextkey'; +import { TerminalContextKeys, TerminalContextKeyStrings } from 'vs/workbench/contrib/terminal/common/terminalContextKey'; +import { registerActiveInstanceAction, terminalSendSequenceCommand } from 'vs/workbench/contrib/terminal/browser/terminalActions'; import { localize2 } from 'vs/nls'; -import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; -import { KeyCode } from 'vs/base/common/keyCodes'; +import { KeybindingsRegistry, KeybindingWeight, type IKeybindings } from 'vs/platform/keybinding/common/keybindingsRegistry'; +import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { TerminalSettingId } from 'vs/platform/terminal/common/terminal'; +import { TerminalSettingId, WindowsShellType } from 'vs/platform/terminal/common/terminal'; +import { CONTEXT_ACCESSIBILITY_MODE_ENABLED } from 'vs/platform/accessibility/common/accessibility'; +import { TerminalSuggestSettingId } from 'vs/workbench/contrib/terminalContrib/suggest/common/terminalSuggestConfiguration'; +import { TerminalSuggestCommandId } from 'vs/workbench/contrib/terminalContrib/suggest/common/terminal.suggest'; + +// #region Terminal Contributions class TerminalSuggestContribution extends DisposableStore implements ITerminalContribution { static readonly ID = 'terminal.suggest'; @@ -84,9 +89,12 @@ class TerminalSuggestContribution extends DisposableStore implements ITerminalCo registerTerminalContribution(TerminalSuggestContribution.ID, TerminalSuggestContribution); -// Actions +// #endregion + +// #region Actions + registerActiveInstanceAction({ - id: TerminalCommandId.SelectPrevSuggestion, + id: TerminalSuggestCommandId.SelectPrevSuggestion, title: localize2('workbench.action.terminal.selectPrevSuggestion', 'Select the Previous Suggestion'), f1: false, precondition: ContextKeyExpr.and(ContextKeyExpr.or(TerminalContextKeys.processSupported, TerminalContextKeys.terminalHasBeenCreated), TerminalContextKeys.focus, TerminalContextKeys.isOpen, TerminalContextKeys.suggestWidgetVisible), @@ -99,7 +107,7 @@ registerActiveInstanceAction({ }); registerActiveInstanceAction({ - id: TerminalCommandId.SelectPrevPageSuggestion, + id: TerminalSuggestCommandId.SelectPrevPageSuggestion, title: localize2('workbench.action.terminal.selectPrevPageSuggestion', 'Select the Previous Page Suggestion'), f1: false, precondition: ContextKeyExpr.and(ContextKeyExpr.or(TerminalContextKeys.processSupported, TerminalContextKeys.terminalHasBeenCreated), TerminalContextKeys.focus, TerminalContextKeys.isOpen, TerminalContextKeys.suggestWidgetVisible), @@ -112,7 +120,7 @@ registerActiveInstanceAction({ }); registerActiveInstanceAction({ - id: TerminalCommandId.SelectNextSuggestion, + id: TerminalSuggestCommandId.SelectNextSuggestion, title: localize2('workbench.action.terminal.selectNextSuggestion', 'Select the Next Suggestion'), f1: false, precondition: ContextKeyExpr.and(ContextKeyExpr.or(TerminalContextKeys.processSupported, TerminalContextKeys.terminalHasBeenCreated), TerminalContextKeys.focus, TerminalContextKeys.isOpen, TerminalContextKeys.suggestWidgetVisible), @@ -125,7 +133,7 @@ registerActiveInstanceAction({ }); registerActiveInstanceAction({ - id: TerminalCommandId.SelectNextPageSuggestion, + id: TerminalSuggestCommandId.SelectNextPageSuggestion, title: localize2('workbench.action.terminal.selectNextPageSuggestion', 'Select the Next Page Suggestion'), f1: false, precondition: ContextKeyExpr.and(ContextKeyExpr.or(TerminalContextKeys.processSupported, TerminalContextKeys.terminalHasBeenCreated), TerminalContextKeys.focus, TerminalContextKeys.isOpen, TerminalContextKeys.suggestWidgetVisible), @@ -138,7 +146,7 @@ registerActiveInstanceAction({ }); registerActiveInstanceAction({ - id: TerminalCommandId.AcceptSelectedSuggestion, + id: TerminalSuggestCommandId.AcceptSelectedSuggestion, title: localize2('workbench.action.terminal.acceptSelectedSuggestion', 'Accept Selected Suggestion'), f1: false, precondition: ContextKeyExpr.and(ContextKeyExpr.or(TerminalContextKeys.processSupported, TerminalContextKeys.terminalHasBeenCreated), TerminalContextKeys.focus, TerminalContextKeys.isOpen, TerminalContextKeys.suggestWidgetVisible), @@ -152,7 +160,7 @@ registerActiveInstanceAction({ }); registerActiveInstanceAction({ - id: TerminalCommandId.HideSuggestWidget, + id: TerminalSuggestCommandId.HideSuggestWidget, title: localize2('workbench.action.terminal.hideSuggestWidget', 'Hide Suggest Widget'), f1: false, precondition: ContextKeyExpr.and(ContextKeyExpr.or(TerminalContextKeys.processSupported, TerminalContextKeys.terminalHasBeenCreated), TerminalContextKeys.focus, TerminalContextKeys.isOpen, TerminalContextKeys.suggestWidgetVisible), @@ -163,3 +171,29 @@ registerActiveInstanceAction({ }, run: (activeInstance) => TerminalSuggestContribution.get(activeInstance)?.addon?.hideSuggestWidget() }); + +// #endregion + +// #region Keybindings + +function registerSendSequenceKeybinding(text: string, rule: { when?: ContextKeyExpression } & IKeybindings): void { + KeybindingsRegistry.registerCommandAndKeybindingRule({ + id: TerminalCommandId.SendSequence, + weight: KeybindingWeight.WorkbenchContrib, + when: rule.when || TerminalContextKeys.focus, + primary: rule.primary, + mac: rule.mac, + linux: rule.linux, + win: rule.win, + handler: terminalSendSequenceCommand, + args: { text } + }); +} + +registerSendSequenceKeybinding(SuggestAddon.requestCompletionsSequence, { // ctrl+space (Native suggest) + when: ContextKeyExpr.and(TerminalContextKeys.focus, ContextKeyExpr.equals(TerminalContextKeyStrings.ShellType, WindowsShellType.PowerShell), TerminalContextKeys.terminalShellIntegrationEnabled, CONTEXT_ACCESSIBILITY_MODE_ENABLED.negate(), ContextKeyExpr.or(ContextKeyExpr.equals(`config.${TerminalSuggestSettingId.Enabled}`, true), ContextKeyExpr.equals(`config.${TerminalSuggestSettingId.EnabledLegacy}`, true))), + primary: KeyMod.CtrlCmd | KeyCode.Space, + mac: { primary: KeyMod.WinCtrl | KeyCode.Space } +}); + +// #endregion diff --git a/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon.ts b/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon.ts index d1a43c5bb56a9..c29c28fba759b 100644 --- a/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon.ts +++ b/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon.ts @@ -16,7 +16,7 @@ import { IContextKey } from 'vs/platform/contextkey/common/contextkey'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { activeContrastBorder } from 'vs/platform/theme/common/colorRegistry'; -import { ISuggestController, ITerminalConfigurationService } from 'vs/workbench/contrib/terminal/browser/terminal'; +import { ITerminalConfigurationService } from 'vs/workbench/contrib/terminal/browser/terminal'; import { TerminalStorageKeys } from 'vs/workbench/contrib/terminal/common/terminalStorageKeys'; import type { ITerminalAddon, Terminal } from '@xterm/xterm'; @@ -72,6 +72,15 @@ const pwshTypeToIconMap: { [type: string]: ThemeIcon | undefined } = { 13: Codicon.symbolKeyword }; +export interface ISuggestController { + selectPreviousSuggestion(): void; + selectPreviousPageSuggestion(): void; + selectNextSuggestion(): void; + selectNextPageSuggestion(): void; + acceptSelectedSuggestion(suggestion?: Pick): void; + hideSuggestWidget(): void; +} + export class SuggestAddon extends Disposable implements ITerminalAddon, ISuggestController { private _terminal?: Terminal; @@ -91,6 +100,8 @@ export class SuggestAddon extends Disposable implements ITerminalAddon, ISuggest private _leadingLineContent?: string; private _cursorIndexDelta: number = 0; + static requestCompletionsSequence = '\x1b[24~e'; // F12,e + private readonly _onBell = this._register(new Emitter()); readonly onBell = this._onBell.event; private readonly _onAcceptedCompletion = this._register(new Emitter()); @@ -140,7 +151,7 @@ export class SuggestAddon extends Disposable implements ITerminalAddon, ISuggest private _requestCompletions(): void { // TODO: Debounce? Prevent this flooding the channel - this._onAcceptedCompletion.fire('\x1b[24~e'); + this._onAcceptedCompletion.fire(SuggestAddon.requestCompletionsSequence); } private _sync(promptInputState: IPromptInputModelState): void { diff --git a/src/vs/workbench/contrib/terminalContrib/suggest/common/terminal.suggest.ts b/src/vs/workbench/contrib/terminalContrib/suggest/common/terminal.suggest.ts new file mode 100644 index 0000000000000..ab4b902ee654c --- /dev/null +++ b/src/vs/workbench/contrib/terminalContrib/suggest/common/terminal.suggest.ts @@ -0,0 +1,22 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +export const enum TerminalSuggestCommandId { + SelectPrevSuggestion = 'workbench.action.terminal.selectPrevSuggestion', + SelectPrevPageSuggestion = 'workbench.action.terminal.selectPrevPageSuggestion', + SelectNextSuggestion = 'workbench.action.terminal.selectNextSuggestion', + SelectNextPageSuggestion = 'workbench.action.terminal.selectNextPageSuggestion', + AcceptSelectedSuggestion = 'workbench.action.terminal.acceptSelectedSuggestion', + HideSuggestWidget = 'workbench.action.terminal.hideSuggestWidget', +} + +export const defaultTerminalSuggestCommandsToSkipShell = [ + TerminalSuggestCommandId.SelectPrevSuggestion, + TerminalSuggestCommandId.SelectPrevPageSuggestion, + TerminalSuggestCommandId.SelectNextSuggestion, + TerminalSuggestCommandId.SelectNextPageSuggestion, + TerminalSuggestCommandId.AcceptSelectedSuggestion, + TerminalSuggestCommandId.HideSuggestWidget, +]; diff --git a/src/vs/workbench/contrib/terminalContrib/suggest/common/terminalSuggestConfiguration.ts b/src/vs/workbench/contrib/terminalContrib/suggest/common/terminalSuggestConfiguration.ts new file mode 100644 index 0000000000000..ad92860dd15ec --- /dev/null +++ b/src/vs/workbench/contrib/terminalContrib/suggest/common/terminalSuggestConfiguration.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. + *--------------------------------------------------------------------------------------------*/ + +import type { IStringDictionary } from 'vs/base/common/collections'; +import { localize } from 'vs/nls'; +import type { IConfigurationPropertySchema } from 'vs/platform/configuration/common/configurationRegistry'; +import { TerminalSettingId } from 'vs/platform/terminal/common/terminal'; + +export const enum TerminalSuggestSettingId { + Enabled = 'terminal.integrated.suggest.enabled', + EnabledLegacy = 'terminal.integrated.shellIntegration.suggestEnabled', + QuickSuggestions = 'terminal.integrated.suggest.quickSuggestions', + SuggestOnTriggerCharacters = 'terminal.integrated.suggest.suggestOnTriggerCharacters', +} + +export interface ITerminalSuggestConfiguration { + +} + +export const terminalSuggestConfiguration: IStringDictionary = { + [TerminalSuggestSettingId.Enabled]: { + restricted: true, + markdownDescription: localize('suggest.enabled', "Enables experimental terminal Intellisense suggestions for supported shells ({0}) when {1} is set to {2}.\n\nIf shell integration is installed manually, {3} needs to be set to {4} before calling the shell integration script.", 'PowerShell', `\`#${TerminalSettingId.ShellIntegrationEnabled}#\``, '`true`', '`VSCODE_SUGGEST`', '`1`'), + type: 'boolean', + default: false, + }, + [TerminalSuggestSettingId.EnabledLegacy]: { + restricted: true, + markdownDescription: localize('suggest.enabled', "Enables experimental terminal Intellisense suggestions for supported shells ({0}) when {1} is set to {2}.\n\nIf shell integration is installed manually, {3} needs to be set to {4} before calling the shell integration script.", 'PowerShell', `\`#${TerminalSettingId.ShellIntegrationEnabled}#\``, '`true`', '`VSCODE_SUGGEST`', '`1`'), + type: 'boolean', + default: false, + markdownDeprecationMessage: localize('suggest.enabled.deprecated', 'This setting is deprecated, please use `{0}` instead.', `\`#${TerminalSuggestSettingId.Enabled}#\``) + }, + [TerminalSuggestSettingId.QuickSuggestions]: { + restricted: true, + markdownDescription: localize('suggest.quickSuggestions', "Controls whether suggestions should automatically show up while typing. Also be aware of the {0}-setting which controls if suggestions are triggered by special characters.", `\`#${TerminalSuggestSettingId.SuggestOnTriggerCharacters}#\``), + type: 'boolean', + default: true, + }, + [TerminalSuggestSettingId.SuggestOnTriggerCharacters]: { + restricted: true, + markdownDescription: localize('suggest.suggestOnTriggerCharacters', "Controls whether suggestions should automatically show up when typing trigger characters."), + type: 'boolean', + default: true, + }, +}; From 83e83422c94025ae1713862263ee54d9e1084a5f Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Mon, 29 Apr 2024 03:13:51 -0700 Subject: [PATCH 079/104] Move suggest config into terminalContrib --- src/vs/workbench/contrib/terminal/common/terminal.ts | 5 ----- .../suggest/browser/terminalSuggestAddon.ts | 10 +++++++--- .../suggest/common/terminalSuggestConfiguration.ts | 6 +++++- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/common/terminal.ts b/src/vs/workbench/contrib/terminal/common/terminal.ts index ce92a42e1b779..406bfbb41cf89 100644 --- a/src/vs/workbench/contrib/terminal/common/terminal.ts +++ b/src/vs/workbench/contrib/terminal/common/terminal.ts @@ -207,11 +207,6 @@ export interface ITerminalConfiguration { // TODO: Legacy - remove soon suggestEnabled: boolean; }; - suggest?: { - enabled: boolean; - quickSuggestions: boolean; - suggestOnTriggerCharacters: boolean; - }; enableImages: boolean; smoothScrolling: boolean; ignoreBracketedPasteMode: boolean; diff --git a/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon.ts b/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon.ts index c29c28fba759b..d46c7f3ae04e8 100644 --- a/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon.ts +++ b/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon.ts @@ -25,6 +25,8 @@ import { TerminalCapability, type ITerminalCapabilityStore } from 'vs/platform/t import type { IPromptInputModel, IPromptInputModelState } from 'vs/platform/terminal/common/capabilities/commandDetection/promptInputModel'; import { ShellIntegrationOscPs } from 'vs/platform/terminal/common/xterm/shellIntegrationAddon'; import type { IXtermCore } from 'vs/workbench/contrib/terminal/browser/xterm-private'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { terminalSuggestConfigSection, type ITerminalSuggestConfiguration } from 'vs/workbench/contrib/terminalContrib/suggest/common/terminalSuggestConfiguration'; const enum VSCodeOscPt { Completions = 'Completions', @@ -110,6 +112,7 @@ export class SuggestAddon extends Disposable implements ITerminalAddon, ISuggest constructor( private readonly _capabilities: ITerminalCapabilityStore, private readonly _terminalSuggestWidgetVisibleContextKey: IContextKey, + @IConfigurationService private readonly _configurationService: IConfigurationService, @IInstantiationService private readonly _instantiationService: IInstantiationService, @ITerminalConfigurationService private readonly _terminalConfigurationService: ITerminalConfigurationService ) { @@ -155,7 +158,8 @@ export class SuggestAddon extends Disposable implements ITerminalAddon, ISuggest } private _sync(promptInputState: IPromptInputModelState): void { - const enabled = this._terminalConfigurationService.config.suggest?.enabled || this._terminalConfigurationService.config.shellIntegration?.suggestEnabled; + const config = this._configurationService.getValue(terminalSuggestConfigSection); + const enabled = config.enabled || this._terminalConfigurationService.config.shellIntegration?.suggestEnabled; if (!enabled) { return; } @@ -166,7 +170,7 @@ export class SuggestAddon extends Disposable implements ITerminalAddon, ISuggest let sent = false; // Quick suggestions - if (this._terminalConfigurationService.config.suggest?.quickSuggestions) { + if (config.quickSuggestions) { const completionPrefix = promptInputState.value.substring(0, promptInputState.cursorIndex); if (promptInputState.cursorIndex === 1 || completionPrefix.match(/([\s\[])[^\s]$/)) { this._requestCompletions(); @@ -175,7 +179,7 @@ export class SuggestAddon extends Disposable implements ITerminalAddon, ISuggest } // Trigger characters - if (this._terminalConfigurationService.config.suggest?.suggestOnTriggerCharacters && !sent) { + if (config.suggestOnTriggerCharacters && !sent) { const lastChar = promptInputState.value.at(promptInputState.cursorIndex - 1); if (lastChar?.match(/[\\\/\-]/)) { this._requestCompletions(); diff --git a/src/vs/workbench/contrib/terminalContrib/suggest/common/terminalSuggestConfiguration.ts b/src/vs/workbench/contrib/terminalContrib/suggest/common/terminalSuggestConfiguration.ts index ad92860dd15ec..f465e37f07653 100644 --- a/src/vs/workbench/contrib/terminalContrib/suggest/common/terminalSuggestConfiguration.ts +++ b/src/vs/workbench/contrib/terminalContrib/suggest/common/terminalSuggestConfiguration.ts @@ -15,8 +15,12 @@ export const enum TerminalSuggestSettingId { SuggestOnTriggerCharacters = 'terminal.integrated.suggest.suggestOnTriggerCharacters', } -export interface ITerminalSuggestConfiguration { +export const terminalSuggestConfigSection = 'terminal.integrated.suggest'; +export interface ITerminalSuggestConfiguration { + enabled: boolean; + quickSuggestions: boolean; + suggestOnTriggerCharacters: boolean; } export const terminalSuggestConfiguration: IStringDictionary = { From 7698c6c266453f370124852d5a11b78791ad0035 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Mon, 29 Apr 2024 13:08:44 +0200 Subject: [PATCH 080/104] Themes: default theme and default colors are no longer in sync (#211629) --- .../services/themes/common/workbenchThemeService.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/services/themes/common/workbenchThemeService.ts b/src/vs/workbench/services/themes/common/workbenchThemeService.ts index f6791507b6252..a7be26f1be154 100644 --- a/src/vs/workbench/services/themes/common/workbenchThemeService.ts +++ b/src/vs/workbench/services/themes/common/workbenchThemeService.ts @@ -60,12 +60,18 @@ export const COLOR_THEME_DARK_INITIAL_COLORS = { 'activityBar.background': '#181818', 'statusBar.background': '#181818', 'statusBar.noFolderBackground': '#1f1f1f', + 'titleBar.border': '#2B2B2B', + 'titleBar.inactiveBackground': '#ff0000', + 'titleBar.inactiveForeground': '#9D9D9D' }; export const COLOR_THEME_LIGHT_INITIAL_COLORS = { 'activityBar.background': '#f8f8f8', 'statusBar.background': '#f8f8f8', - 'statusBar.noFolderBackground': '#f8f8f8' + 'statusBar.noFolderBackground': '#f8f8f8', + 'titleBar.border': '#E5E5E5', + 'titleBar.inactiveBackground': '#F8F8F8', + 'titleBar.inactiveForeground': '#8B949E', }; export interface IWorkbenchTheme { From 65d749d038419be0d87a135ce40d3e29f5fd6eda Mon Sep 17 00:00:00 2001 From: Benjamin Christopher Simmonds <44439583+benibenj@users.noreply.github.com> Date: Mon, 29 Apr 2024 13:09:08 +0200 Subject: [PATCH 081/104] Fix drag feedback in activity bar when `contrastActiveBorder` is set (#211628) Activity Bar Contrast border fix #211626 --- .../parts/activitybar/activitybarPart.ts | 39 +++++-------------- 1 file changed, 10 insertions(+), 29 deletions(-) diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index a3fc3c07785f9..4610ddff2c38f 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -614,43 +614,24 @@ registerThemingParticipant((theme, collector) => { const outline = theme.getColor(activeContrastBorder); if (outline) { collector.addRule(` - .monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item:before { - content: ""; - position: absolute; - display: block; - top: 8px; - left: 8px; - height: 32px; - width: 32px; - z-index: 1; + .monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item .action-label::before{ + padding: 6px; } - .monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.profile-activity-item:before { - top: -6px; + .monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.active .action-label::before, + .monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.active:hover .action-label::before, + .monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.checked .action-label::before, + .monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.checked:hover .action-label::before { + outline: 1px solid ${outline}; } - .monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.active:before, - .monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.active:hover:before, - .monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.checked:before, - .monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.checked:hover:before { - outline: 1px solid; - } - - .monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item:hover:before { - outline: 1px dashed; + .monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item:hover .action-label::before { + outline: 1px dashed ${outline}; } .monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item:focus .active-item-indicator:before { border-left-color: ${outline}; } - - .monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.active:before, - .monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.active:hover:before, - .monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.checked:before, - .monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.checked:hover:before, - .monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item:hover:before { - outline-color: ${outline}; - } `); } @@ -659,7 +640,7 @@ registerThemingParticipant((theme, collector) => { const focusBorderColor = theme.getColor(focusBorder); if (focusBorderColor) { collector.addRule(` - .monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item:focus .active-item-indicator:before { + .monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item:focus .active-item-indicator::before { border-left-color: ${focusBorderColor}; } `); From 1867e88862ca26343822231267f20b839daef65d Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Mon, 29 Apr 2024 15:15:12 +0200 Subject: [PATCH 082/104] Context menu grouping is broken (#211625) (#211634) * Context menu grouping is broken Fixes #211488 * Make grouping explicit --- .../workbench/browser/parts/views/treeView.ts | 70 +++++++++++++------ 1 file changed, 48 insertions(+), 22 deletions(-) diff --git a/src/vs/workbench/browser/parts/views/treeView.ts b/src/vs/workbench/browser/parts/views/treeView.ts index ee77e91b7333b..6bf667dda1074 100644 --- a/src/vs/workbench/browser/parts/views/treeView.ts +++ b/src/vs/workbench/browser/parts/views/treeView.ts @@ -13,7 +13,7 @@ import { IIdentityProvider, IListVirtualDelegate } from 'vs/base/browser/ui/list import { ElementsDragAndDropData, ListViewTargetSector } from 'vs/base/browser/ui/list/listView'; import { IAsyncDataSource, ITreeContextMenuEvent, ITreeDragAndDrop, ITreeDragOverReaction, ITreeNode, ITreeRenderer, TreeDragOverBubble } from 'vs/base/browser/ui/tree/tree'; import { CollapseAllAction } from 'vs/base/browser/ui/tree/treeDefaults'; -import { ActionRunner, IAction } from 'vs/base/common/actions'; +import { ActionRunner, IAction, Separator } from 'vs/base/common/actions'; import { timeout } from 'vs/base/common/async'; import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation'; import { Codicon } from 'vs/base/common/codicons'; @@ -1599,13 +1599,53 @@ class TreeMenus implements IDisposable { this.contextKeyService = service; } + private filterNonUniversalActions(groups: Map[], newActions: IAction[]) { + const newActionsSet: Set = new Set(newActions.map(a => a.id)); + for (const group of groups) { + const actions = group.keys(); + for (const action of actions) { + if (!newActionsSet.has(action)) { + group.delete(action); + } + } + } + } + + private buildMenu(groups: Map[]): IAction[] { + const result: IAction[] = []; + for (const group of groups) { + if (group.size > 0) { + if (result.length) { + result.push(new Separator()); + } + result.push(...group.values()); + } + } + return result; + } + + private createGroups(actions: IAction[]): Map[] { + const groups: Map[] = []; + let group: Map = new Map(); + for (const action of actions) { + if (action instanceof Separator) { + groups.push(group); + group = new Map(); + } else { + group.set(action.id, action); + } + } + groups.push(group); + return groups; + } + private getActions(menuId: MenuId, elements: ITreeItem[], listen?: DisposableStore): { primary: IAction[]; secondary: IAction[] } { if (!this.contextKeyService) { return { primary: [], secondary: [] }; } - const allowedPrimary = new Map(); - const allowedSecondary = new Map(); + let primaryGroups: Map[] = []; + let secondaryGroups: Map[] = []; for (let i = 0; i < elements.length; i++) { const element = elements[i]; const contextKeyService = this.contextKeyService.createOverlay([ @@ -1619,25 +1659,11 @@ class TreeMenus implements IDisposable { const result = { primary, secondary, menu }; createAndFillInContextMenuActions(menu, { shouldForwardArgs: true }, result, 'inline'); if (i === 0) { - for (const action of result.primary) { - allowedPrimary.set(action.id, action); - } - for (const action of result.secondary) { - allowedSecondary.set(action.id, action); - } + primaryGroups = this.createGroups(result.primary); + secondaryGroups = this.createGroups(result.secondary); } else { - const primaryKeys = allowedPrimary.keys(); - for (const key of primaryKeys) { - if (!result.primary.some(action => action.id === key)) { - allowedPrimary.delete(key); - } - } - const secondaryKeys = allowedSecondary.keys(); - for (const key of secondaryKeys) { - if (!result.secondary.some(action => action.id === key)) { - allowedSecondary.delete(key); - } - } + this.filterNonUniversalActions(primaryGroups, result.primary); + this.filterNonUniversalActions(secondaryGroups, result.secondary); } if (listen && elements.length === 1) { listen.add(menu.onDidChange(() => this._onDidChange.fire(element))); @@ -1647,7 +1673,7 @@ class TreeMenus implements IDisposable { } } - return { primary: Array.from(allowedPrimary.values()), secondary: Array.from(allowedSecondary.values()) }; + return { primary: this.buildMenu(primaryGroups), secondary: this.buildMenu(secondaryGroups) }; } dispose() { From 0134c02972b222100a7530247c87a033b1a3b257 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Mon, 29 Apr 2024 07:36:53 -0700 Subject: [PATCH 083/104] Fix build --- .../terminal/browser/terminal.contribution.ts | 9 ++++ .../browser/terminal.suggest.contribution.ts | 48 +++++-------------- 2 files changed, 20 insertions(+), 37 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts b/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts index 84953ef53b0e6..96657abf2ac17 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts @@ -56,6 +56,10 @@ import { registerTerminalConfiguration } from 'vs/workbench/contrib/terminal/com import { TerminalContextKeyStrings, TerminalContextKeys } from 'vs/workbench/contrib/terminal/common/terminalContextKey'; import { terminalStrings } from 'vs/workbench/contrib/terminal/common/terminalStrings'; +// HACK: This file should not depend on terminalContrib +// eslint-disable-next-line local/code-import-patterns +import { TerminalSuggestSettingId } from 'vs/workbench/contrib/terminalContrib/suggest/common/terminalSuggestConfiguration'; + // Register services registerSingleton(ITerminalLogService, TerminalLogService, InstantiationType.Delayed); registerSingleton(ITerminalConfigurationService, TerminalConfigurationService, InstantiationType.Delayed); @@ -205,6 +209,11 @@ registerSendSequenceKeybinding('\x1b[24~d', { // F12,d -> shift+end (SelectLine) when: ContextKeyExpr.and(TerminalContextKeys.focus, ContextKeyExpr.equals(TerminalContextKeyStrings.ShellType, WindowsShellType.PowerShell), TerminalContextKeys.terminalShellIntegrationEnabled, CONTEXT_ACCESSIBILITY_MODE_ENABLED.negate()), mac: { primary: KeyMod.Shift | KeyMod.CtrlCmd | KeyCode.RightArrow } }); +registerSendSequenceKeybinding('\x1b[24~e', { // F12,e -> ctrl+space (Native suggest) + when: ContextKeyExpr.and(TerminalContextKeys.focus, ContextKeyExpr.equals(TerminalContextKeyStrings.ShellType, WindowsShellType.PowerShell), TerminalContextKeys.terminalShellIntegrationEnabled, CONTEXT_ACCESSIBILITY_MODE_ENABLED.negate(), ContextKeyExpr.or(ContextKeyExpr.equals(`config.${TerminalSuggestSettingId.Enabled}`, true), ContextKeyExpr.equals(`config.${TerminalSuggestSettingId.EnabledLegacy}`, true))), + primary: KeyMod.CtrlCmd | KeyCode.Space, + mac: { primary: KeyMod.WinCtrl | KeyCode.Space } +}); // Always on pwsh keybindings registerSendSequenceKeybinding('\x1b[1;2H', { // Shift+home diff --git a/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminal.suggest.contribution.ts b/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminal.suggest.contribution.ts index fe1a317de539e..7a781570251a5 100644 --- a/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminal.suggest.contribution.ts +++ b/src/vs/workbench/contrib/terminalContrib/suggest/browser/terminal.suggest.contribution.ts @@ -3,25 +3,23 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import type { Terminal as RawXtermTerminal } from '@xterm/xterm'; import * as dom from 'vs/base/browser/dom'; -import { DisposableStore, toDisposable, MutableDisposable } from 'vs/base/common/lifecycle'; +import { KeyCode } from 'vs/base/common/keyCodes'; +import { DisposableStore, MutableDisposable, toDisposable } from 'vs/base/common/lifecycle'; +import { localize2 } from 'vs/nls'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { ContextKeyExpr, IContextKey, IContextKeyService, IReadableSet } from 'vs/platform/contextkey/common/contextkey'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; +import { TerminalSettingId } from 'vs/platform/terminal/common/terminal'; import { ITerminalContribution, ITerminalInstance, IXtermTerminal } from 'vs/workbench/contrib/terminal/browser/terminal'; +import { registerActiveInstanceAction } from 'vs/workbench/contrib/terminal/browser/terminalActions'; import { registerTerminalContribution } from 'vs/workbench/contrib/terminal/browser/terminalExtensions'; import { TerminalWidgetManager } from 'vs/workbench/contrib/terminal/browser/widgets/widgetManager'; +import { ITerminalConfiguration, ITerminalProcessManager, TERMINAL_CONFIG_SECTION } from 'vs/workbench/contrib/terminal/common/terminal'; +import { TerminalContextKeys } from 'vs/workbench/contrib/terminal/common/terminalContextKey'; import { SuggestAddon } from 'vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon'; -import { ITerminalConfiguration, ITerminalProcessManager, TERMINAL_CONFIG_SECTION, TerminalCommandId } from 'vs/workbench/contrib/terminal/common/terminal'; -import type { Terminal as RawXtermTerminal } from '@xterm/xterm'; -import { ContextKeyExpr, IContextKey, IContextKeyService, IReadableSet, type ContextKeyExpression } from 'vs/platform/contextkey/common/contextkey'; -import { TerminalContextKeys, TerminalContextKeyStrings } from 'vs/workbench/contrib/terminal/common/terminalContextKey'; -import { registerActiveInstanceAction, terminalSendSequenceCommand } from 'vs/workbench/contrib/terminal/browser/terminalActions'; -import { localize2 } from 'vs/nls'; -import { KeybindingsRegistry, KeybindingWeight, type IKeybindings } from 'vs/platform/keybinding/common/keybindingsRegistry'; -import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; -import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { TerminalSettingId, WindowsShellType } from 'vs/platform/terminal/common/terminal'; -import { CONTEXT_ACCESSIBILITY_MODE_ENABLED } from 'vs/platform/accessibility/common/accessibility'; -import { TerminalSuggestSettingId } from 'vs/workbench/contrib/terminalContrib/suggest/common/terminalSuggestConfiguration'; import { TerminalSuggestCommandId } from 'vs/workbench/contrib/terminalContrib/suggest/common/terminal.suggest'; // #region Terminal Contributions @@ -173,27 +171,3 @@ registerActiveInstanceAction({ }); // #endregion - -// #region Keybindings - -function registerSendSequenceKeybinding(text: string, rule: { when?: ContextKeyExpression } & IKeybindings): void { - KeybindingsRegistry.registerCommandAndKeybindingRule({ - id: TerminalCommandId.SendSequence, - weight: KeybindingWeight.WorkbenchContrib, - when: rule.when || TerminalContextKeys.focus, - primary: rule.primary, - mac: rule.mac, - linux: rule.linux, - win: rule.win, - handler: terminalSendSequenceCommand, - args: { text } - }); -} - -registerSendSequenceKeybinding(SuggestAddon.requestCompletionsSequence, { // ctrl+space (Native suggest) - when: ContextKeyExpr.and(TerminalContextKeys.focus, ContextKeyExpr.equals(TerminalContextKeyStrings.ShellType, WindowsShellType.PowerShell), TerminalContextKeys.terminalShellIntegrationEnabled, CONTEXT_ACCESSIBILITY_MODE_ENABLED.negate(), ContextKeyExpr.or(ContextKeyExpr.equals(`config.${TerminalSuggestSettingId.Enabled}`, true), ContextKeyExpr.equals(`config.${TerminalSuggestSettingId.EnabledLegacy}`, true))), - primary: KeyMod.CtrlCmd | KeyCode.Space, - mac: { primary: KeyMod.WinCtrl | KeyCode.Space } -}); - -// #endregion From 547b3f3df276b209838305992d1a6c8866d84892 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 29 Apr 2024 18:00:27 +0200 Subject: [PATCH 084/104] `visibleTextEditorControls` in the editor service doesn't return all visible text editor controls (fix #211357) (#211643) --- .../contrib/scm/browser/dirtydiffDecorator.ts | 28 ++----------------- .../services/editor/browser/editorService.ts | 18 +++++++++--- .../services/editor/common/editorService.ts | 3 ++ 3 files changed, 19 insertions(+), 30 deletions(-) diff --git a/src/vs/workbench/contrib/scm/browser/dirtydiffDecorator.ts b/src/vs/workbench/contrib/scm/browser/dirtydiffDecorator.ts index 47a1db3d92c89..7537f80f534cd 100644 --- a/src/vs/workbench/contrib/scm/browser/dirtydiffDecorator.ts +++ b/src/vs/workbench/contrib/scm/browser/dirtydiffDecorator.ts @@ -58,10 +58,6 @@ import { AccessibilitySignal, IAccessibilitySignalService } from 'vs/platform/ac import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; import { IQuickDiffService, QuickDiff } from 'vs/workbench/contrib/scm/common/quickDiff'; import { IQuickDiffSelectItem, SwitchQuickDiffBaseAction, SwitchQuickDiffViewItem } from 'vs/workbench/contrib/scm/browser/dirtyDiffSwitcher'; -import { TextDiffEditor } from 'vs/workbench/browser/parts/editor/textDiffEditor'; -import { IEditorControl } from 'vs/workbench/common/editor'; -import { TextFileEditor } from 'vs/workbench/contrib/files/browser/editors/textFileEditor'; -import { SideBySideEditor } from 'vs/workbench/browser/parts/editor/sideBySideEditor'; class DiffActionRunner extends ActionRunner { @@ -1653,28 +1649,8 @@ export class DirtyDiffWorkbenchController extends Disposable implements ext.IWor this.enabled = false; } - private getVisibleEditorControls(): IEditorControl[] { - const controls: IEditorControl[] = []; - const addControl = (control: IEditorControl | undefined) => { - if (control) { - controls.push(control); - } - }; - - for (const editorPane of this.editorService.visibleEditorPanes) { - if (editorPane instanceof TextDiffEditor || editorPane instanceof TextFileEditor) { - addControl(editorPane.getControl()); - } else if (editorPane instanceof SideBySideEditor) { - addControl(editorPane.getPrimaryEditorPane()?.getControl()); - addControl(editorPane.getSecondaryEditorPane()?.getControl()); - } - } - return controls; - } - private onEditorsChanged(): void { - const visibleControls = this.getVisibleEditorControls(); - for (const editor of visibleControls) { + for (const editor of this.editorService.visibleTextEditorControls) { if (isCodeEditor(editor)) { const textModel = editor.getModel(); const controller = DirtyDiffController.get(editor); @@ -1700,7 +1676,7 @@ export class DirtyDiffWorkbenchController extends Disposable implements ext.IWor for (const [uri, item] of this.items) { for (const editorId of item.keys()) { - if (!this.getVisibleEditorControls().find(editor => isCodeEditor(editor) && editor.getModel()?.uri.toString() === uri.toString() && editor.getId() === editorId)) { + if (!this.editorService.visibleTextEditorControls.find(editor => isCodeEditor(editor) && editor.getModel()?.uri.toString() === uri.toString() && editor.getId() === editorId)) { if (item.has(editorId)) { const dirtyDiffItem = item.get(editorId); dirtyDiffItem?.dispose(); diff --git a/src/vs/workbench/services/editor/browser/editorService.ts b/src/vs/workbench/services/editor/browser/editorService.ts index 6b0dc0e8e2d6d..cd6d5c6f86ee4 100644 --- a/src/vs/workbench/services/editor/browser/editorService.ts +++ b/src/vs/workbench/services/editor/browser/editorService.ts @@ -5,7 +5,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IResourceEditorInput, IEditorOptions, EditorActivation, IResourceEditorInputIdentifier, ITextResourceEditorInput } from 'vs/platform/editor/common/editor'; -import { SideBySideEditor, IEditorPane, GroupIdentifier, IUntitledTextResourceEditorInput, IResourceDiffEditorInput, EditorInputWithOptions, isEditorInputWithOptions, IEditorIdentifier, IEditorCloseEvent, ITextDiffEditorPane, IRevertOptions, SaveReason, EditorsOrder, IWorkbenchEditorConfiguration, EditorResourceAccessor, IVisibleEditorPane, EditorInputCapabilities, isResourceDiffEditorInput, IUntypedEditorInput, isResourceEditorInput, isEditorInput, isEditorInputWithOptionsAndGroup, IFindEditorOptions, isResourceMergeEditorInput, IEditorWillOpenEvent } from 'vs/workbench/common/editor'; +import { SideBySideEditor, IEditorPane, GroupIdentifier, IUntitledTextResourceEditorInput, IResourceDiffEditorInput, EditorInputWithOptions, isEditorInputWithOptions, IEditorIdentifier, IEditorCloseEvent, ITextDiffEditorPane, IRevertOptions, SaveReason, EditorsOrder, IWorkbenchEditorConfiguration, EditorResourceAccessor, IVisibleEditorPane, EditorInputCapabilities, isResourceDiffEditorInput, IUntypedEditorInput, isResourceEditorInput, isEditorInput, isEditorInputWithOptionsAndGroup, IFindEditorOptions, isResourceMergeEditorInput, IEditorWillOpenEvent, IEditorControl } from 'vs/workbench/common/editor'; import { EditorInput } from 'vs/workbench/common/editor/editorInput'; import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditorInput'; import { ResourceMap, ResourceSet } from 'vs/base/common/map'; @@ -14,6 +14,7 @@ import { Event, Emitter } from 'vs/base/common/event'; import { URI } from 'vs/base/common/uri'; import { joinPath } from 'vs/base/common/resources'; import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput'; +import { SideBySideEditor as SideBySideEditorPane } from 'vs/workbench/browser/parts/editor/sideBySideEditor'; import { IEditorGroupsService, IEditorGroup, GroupsOrder, IEditorReplacement, isEditorReplacement, ICloseEditorOptions, IEditorGroupsContainer } from 'vs/workbench/services/editor/common/editorGroupsService'; import { IUntypedEditorReplacement, IEditorService, ISaveEditorsOptions, ISaveAllEditorsOptions, IRevertAllEditorsOptions, IBaseSaveRevertAllEditorOptions, IOpenEditorsOptions, PreferredGroup, isPreferredGroup, IEditorsChangeEvent, ISaveEditorsResult } from 'vs/workbench/services/editor/common/editorService'; import { IConfigurationChangeEvent, IConfigurationService } from 'vs/platform/configuration/common/configuration'; @@ -491,9 +492,18 @@ export class EditorService extends Disposable implements EditorServiceImpl { get visibleTextEditorControls(): Array { const visibleTextEditorControls: Array = []; for (const visibleEditorPane of this.visibleEditorPanes) { - const control = visibleEditorPane.getControl(); - if (isCodeEditor(control) || isDiffEditor(control)) { - visibleTextEditorControls.push(control); + const controls: Array = []; + if (visibleEditorPane instanceof SideBySideEditorPane) { + controls.push(visibleEditorPane.getPrimaryEditorPane()?.getControl()); + controls.push(visibleEditorPane.getSecondaryEditorPane()?.getControl()); + } else { + controls.push(visibleEditorPane.getControl()); + } + + for (const control of controls) { + if (isCodeEditor(control) || isDiffEditor(control)) { + visibleTextEditorControls.push(control); + } } } diff --git a/src/vs/workbench/services/editor/common/editorService.ts b/src/vs/workbench/services/editor/common/editorService.ts index 1be2060f98c72..a44e9fd4f4f62 100644 --- a/src/vs/workbench/services/editor/common/editorService.ts +++ b/src/vs/workbench/services/editor/common/editorService.ts @@ -207,6 +207,9 @@ export interface IEditorService { /** * All text editor widgets that are currently visible across all editor groups. A text editor * widget is either a text or a diff editor. + * + * This property supports side-by-side editors as well, by returning both sides if they are + * text editor widgets. */ readonly visibleTextEditorControls: readonly (IEditor | IDiffEditor)[]; From c1cc1a902d9c91f8754981cabe9a80af8d061ea1 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 29 Apr 2024 09:23:51 -0700 Subject: [PATCH 085/104] Remove most `` assertions in TS ext (#211648) These can easily hide typing errors --- .../src/commands/openJsDocLink.ts | 4 +- .../src/filesystems/memFs.ts | 79 +++++++++---------- .../src/utils/arrays.ts | 2 +- 3 files changed, 42 insertions(+), 43 deletions(-) diff --git a/extensions/typescript-language-features/src/commands/openJsDocLink.ts b/extensions/typescript-language-features/src/commands/openJsDocLink.ts index 2b7371ea6de2a..8535fb1c239a9 100644 --- a/extensions/typescript-language-features/src/commands/openJsDocLink.ts +++ b/extensions/typescript-language-features/src/commands/openJsDocLink.ts @@ -32,8 +32,8 @@ export class OpenJsDocLinkCommand implements Command { public async execute(args: OpenJsDocLinkCommand_Args): Promise { const { line, character } = args.position; const position = new vscode.Position(line, character); - await vscode.commands.executeCommand('vscode.open', vscode.Uri.from(args.file), { + await vscode.commands.executeCommand('vscode.open', vscode.Uri.from(args.file), { selection: new vscode.Range(position, position), - }); + } satisfies vscode.TextDocumentShowOptions); } } diff --git a/extensions/typescript-language-features/src/filesystems/memFs.ts b/extensions/typescript-language-features/src/filesystems/memFs.ts index 02476ec180426..eeeb60e957d3b 100644 --- a/extensions/typescript-language-features/src/filesystems/memFs.ts +++ b/extensions/typescript-language-features/src/filesystems/memFs.ts @@ -8,7 +8,7 @@ import { basename, dirname } from 'path'; export class MemFs implements vscode.FileSystemProvider { - private readonly root = new FsEntry( + private readonly root = new FsDirectoryEntry( new Map(), 0, 0, @@ -31,8 +31,11 @@ export class MemFs implements vscode.FileSystemProvider { if (!entry) { throw vscode.FileSystemError.FileNotFound(); } + if (!(entry instanceof FsDirectoryEntry)) { + throw vscode.FileSystemError.FileNotADirectory(); + } - return [...entry.contents.entries()].map(([name, entry]) => [name, entry.type]); + return Array.from(entry.contents.entries(), ([name, entry]) => [name, entry.type]); } readFile(uri: vscode.Uri): Uint8Array { @@ -43,6 +46,10 @@ export class MemFs implements vscode.FileSystemProvider { throw vscode.FileSystemError.FileNotFound(); } + if (!(entry instanceof FsFileEntry)) { + throw vscode.FileSystemError.FileIsADirectory(uri); + } + return entry.data; } @@ -58,12 +65,16 @@ export class MemFs implements vscode.FileSystemProvider { const entry = dirContents.get(basename(uri.path)); if (!entry) { if (create) { - dirContents.set(fileName, new FsEntry(content, time, time)); + dirContents.set(fileName, new FsFileEntry(content, time, time)); this._emitter.fire([{ type: vscode.FileChangeType.Created, uri }]); } else { throw vscode.FileSystemError.FileNotFound(); } } else { + if (entry instanceof FsDirectoryEntry) { + throw vscode.FileSystemError.FileIsADirectory(uri); + } + if (overwrite) { entry.mtime = time; entry.data = content; @@ -90,10 +101,10 @@ export class MemFs implements vscode.FileSystemProvider { // console.log('createDirectory', uri.toString()); const dir = this.getParent(uri); const now = Date.now() / 1000; - dir.contents.set(basename(uri.path), new FsEntry(new Map(), now, now)); + dir.contents.set(basename(uri.path), new FsDirectoryEntry(new Map(), now, now)); } - private getEntry(uri: vscode.Uri): FsEntry | void { + private getEntry(uri: vscode.Uri): FsEntry | undefined { // TODO: have this throw FileNotFound itself? // TODO: support configuring case sensitivity let node: FsEntry = this.root; @@ -104,13 +115,12 @@ export class MemFs implements vscode.FileSystemProvider { continue; } - if (node.type !== vscode.FileType.Directory) { + if (!(node instanceof FsDirectoryEntry)) { // We're looking at a File or such, so bail. return; } const next = node.contents.get(component); - if (!next) { // not found! return; @@ -121,11 +131,14 @@ export class MemFs implements vscode.FileSystemProvider { return node; } - private getParent(uri: vscode.Uri) { + private getParent(uri: vscode.Uri): FsDirectoryEntry { const dir = this.getEntry(uri.with({ path: dirname(uri.path) })); if (!dir) { throw vscode.FileSystemError.FileNotFound(); } + if (!(dir instanceof FsDirectoryEntry)) { + throw vscode.FileSystemError.FileNotADirectory(); + } return dir; } @@ -153,46 +166,32 @@ export class MemFs implements vscode.FileSystemProvider { } } -class FsEntry { - get type(): vscode.FileType { - if (this._data instanceof Uint8Array) { - return vscode.FileType.File; - } else { - return vscode.FileType.Directory; - } - } +class FsFileEntry { + readonly type = vscode.FileType.File; get size(): number { - if (this.type === vscode.FileType.Directory) { - return [...this.contents.values()].reduce((acc: number, entry: FsEntry) => acc + entry.size, 0); - } else { - return this.data.length; - } + return this.data.length; } constructor( - private _data: Uint8Array | Map, - public ctime: number, + public data: Uint8Array, + public readonly ctime: number, public mtime: number, ) { } +} - get data() { - if (this.type === vscode.FileType.Directory) { - throw vscode.FileSystemError.FileIsADirectory; - } - return this._data; - } - set data(val: Uint8Array) { - if (this.type === vscode.FileType.Directory) { - throw vscode.FileSystemError.FileIsADirectory; - } - this._data = val; - } +class FsDirectoryEntry { + readonly type = vscode.FileType.Directory; - get contents() { - if (this.type !== vscode.FileType.Directory) { - throw vscode.FileSystemError.FileNotADirectory; - } - return >this._data; + get size(): number { + return [...this.contents.values()].reduce((acc: number, entry: FsEntry) => acc + entry.size, 0); } + + constructor( + public readonly contents: Map, + public readonly ctime: number, + public readonly mtime: number, + ) { } } + +type FsEntry = FsFileEntry | FsDirectoryEntry; diff --git a/extensions/typescript-language-features/src/utils/arrays.ts b/extensions/typescript-language-features/src/utils/arrays.ts index a25bbe547330d..61850a3de3ed8 100644 --- a/extensions/typescript-language-features/src/utils/arrays.ts +++ b/extensions/typescript-language-features/src/utils/arrays.ts @@ -20,5 +20,5 @@ export function equals( } export function coalesce(array: ReadonlyArray): T[] { - return array.filter(e => !!e); + return array.filter((e): e is T => !!e); } From d91b7c62bf219031638f29dddc1bd44fc5a39302 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 29 Apr 2024 09:35:47 -0700 Subject: [PATCH 086/104] Remove some extra type assertions (#211650) Removing these as they can hide typing errors --- src/vs/base/common/arrays.ts | 2 +- .../browser/controller/pointerHandler.ts | 2 +- .../api/common/extHostDebugService.ts | 5 +++-- .../workbench/api/common/extHostQuickOpen.ts | 2 +- .../test/browser/mainThreadTreeViews.test.ts | 2 +- .../contrib/chat/browser/chatListRenderer.ts | 8 +++---- .../debug/test/browser/baseDebugView.test.ts | 2 +- .../contrib/debug/test/browser/repl.test.ts | 18 +++++++-------- .../browser/controller/editActions.ts | 2 +- .../contrib/search/browser/searchModel.ts | 2 +- .../tasks/browser/abstractTaskService.ts | 8 +++---- .../test/browser/configurationEditing.test.ts | 2 +- .../test/browser/configurationService.test.ts | 22 +++++++++---------- .../fileDialogService.test.ts | 2 +- .../browser/extensionStorageMigration.test.ts | 2 +- .../search/test/common/searchHelpers.test.ts | 18 +++++++-------- .../views/common/viewContainerModel.ts | 4 ++-- .../test/browser/viewContainerModel.test.ts | 2 +- .../browser/viewDescriptorService.test.ts | 2 +- .../workbench/test/browser/codeeditor.test.ts | 2 +- 20 files changed, 55 insertions(+), 54 deletions(-) diff --git a/src/vs/base/common/arrays.ts b/src/vs/base/common/arrays.ts index c1e97565a1605..a0a169b7f9f32 100644 --- a/src/vs/base/common/arrays.ts +++ b/src/vs/base/common/arrays.ts @@ -341,7 +341,7 @@ function topStep(array: ReadonlyArray, compare: (a: T, b: T) => number, re * @returns New array with all falsy values removed. The original array IS NOT modified. */ export function coalesce(array: ReadonlyArray): T[] { - return array.filter(e => !!e); + return array.filter((e): e is T => !!e); } /** diff --git a/src/vs/editor/browser/controller/pointerHandler.ts b/src/vs/editor/browser/controller/pointerHandler.ts index 1ae9ecab36124..2019016ac4ce2 100644 --- a/src/vs/editor/browser/controller/pointerHandler.ts +++ b/src/vs/editor/browser/controller/pointerHandler.ts @@ -33,7 +33,7 @@ export class PointerEventHandler extends MouseHandler { this._lastPointerType = 'mouse'; this._register(dom.addDisposableListener(this.viewHelper.linesContentDomNode, 'pointerdown', (e: any) => { - const pointerType = e.pointerType; + const pointerType = e.pointerType; if (pointerType === 'mouse') { this._lastPointerType = 'mouse'; return; diff --git a/src/vs/workbench/api/common/extHostDebugService.ts b/src/vs/workbench/api/common/extHostDebugService.ts index 2970a9c3729c7..d39a2dc0d8eff 100644 --- a/src/vs/workbench/api/common/extHostDebugService.ts +++ b/src/vs/workbench/api/common/extHostDebugService.ts @@ -29,6 +29,7 @@ import { toDisposable } from 'vs/base/common/lifecycle'; import { ThemeIcon as ThemeIconUtils } from 'vs/base/common/themables'; import { IExtHostCommands } from 'vs/workbench/api/common/extHostCommands'; import * as Convert from 'vs/workbench/api/common/extHostTypeConverters'; +import { coalesce } from 'vs/base/common/arrays'; export const IExtHostDebugService = createDecorator('IExtHostDebugService'); @@ -935,7 +936,7 @@ export abstract class ExtHostDebugServiceBase implements IExtHostDebugService, E private definesDebugType(ed: IExtensionDescription, type: string) { if (ed.contributes) { - const debuggers = ed.contributes['debuggers']; + const debuggers = ed.contributes['debuggers']; if (debuggers && debuggers.length > 0) { for (const dbg of debuggers) { // only debugger contributions with a "label" are considered a "defining" debugger contribution @@ -961,7 +962,7 @@ export abstract class ExtHostDebugServiceBase implements IExtHostDebugService, E return Promise.race([ Promise.all(promises).then(result => { - const trackers = result.filter(t => !!t); // filter null + const trackers = coalesce(result); // filter null if (trackers.length > 0) { return new MultiTracker(trackers); } diff --git a/src/vs/workbench/api/common/extHostQuickOpen.ts b/src/vs/workbench/api/common/extHostQuickOpen.ts index edc8a951ffce0..b850be83f8642 100644 --- a/src/vs/workbench/api/common/extHostQuickOpen.ts +++ b/src/vs/workbench/api/common/extHostQuickOpen.ts @@ -64,7 +64,7 @@ export function createExtHostQuickOpen(mainContext: IMainContext, workspace: IEx // clear state from last invocation this._onDidSelectItem = undefined; - const itemsPromise = >Promise.resolve(itemsOrItemsPromise); + const itemsPromise = Promise.resolve(itemsOrItemsPromise); const instance = ++this._instances; diff --git a/src/vs/workbench/api/test/browser/mainThreadTreeViews.test.ts b/src/vs/workbench/api/test/browser/mainThreadTreeViews.test.ts index ada06633cf8d2..57b58ab67f6aa 100644 --- a/src/vs/workbench/api/test/browser/mainThreadTreeViews.test.ts +++ b/src/vs/workbench/api/test/browser/mainThreadTreeViews.test.ts @@ -54,7 +54,7 @@ suite('MainThreadHostTreeView', function () { const disposables = ensureNoDisposablesAreLeakedInTestSuite(); setup(async () => { - const instantiationService: TestInstantiationService = workbenchInstantiationService(undefined, disposables); + const instantiationService: TestInstantiationService = workbenchInstantiationService(undefined, disposables); const viewDescriptorService = disposables.add(instantiationService.createInstance(ViewDescriptorService)); instantiationService.stub(IViewDescriptorService, viewDescriptorService); container = Registry.as(Extensions.ViewContainersRegistry).registerViewContainer({ id: 'testContainer', title: nls.localize2('test', 'test'), ctorDescriptor: new SyncDescriptor({}) }, ViewContainerLocation.Sidebar); diff --git a/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts b/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts index d4133e7f8277d..ed6193be46ac1 100644 --- a/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts +++ b/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts @@ -1258,8 +1258,8 @@ class TreePool extends Disposable { const container = $('.interactive-response-progress-tree'); this._register(createFileIconThemableTreeContainerScope(container, this.themeService)); - const tree = >this.instantiationService.createInstance( - WorkbenchCompressibleAsyncDataTree, + const tree = this.instantiationService.createInstance( + WorkbenchCompressibleAsyncDataTree, 'ChatListRenderer', container, new ChatListTreeDelegate(), @@ -1318,8 +1318,8 @@ class ContentReferencesListPool extends Disposable { const container = $('.chat-used-context-list'); this._register(createFileIconThemableTreeContainerScope(container, this.themeService)); - const list = >this.instantiationService.createInstance( - WorkbenchList, + const list = this.instantiationService.createInstance( + WorkbenchList, 'ChatListRenderer', container, new ContentReferencesListDelegate(), diff --git a/src/vs/workbench/contrib/debug/test/browser/baseDebugView.test.ts b/src/vs/workbench/contrib/debug/test/browser/baseDebugView.test.ts index 5df2308f69154..075791be12aef 100644 --- a/src/vs/workbench/contrib/debug/test/browser/baseDebugView.test.ts +++ b/src/vs/workbench/contrib/debug/test/browser/baseDebugView.test.ts @@ -31,7 +31,7 @@ suite('Debug - Base Debug View', () => { * Instantiate services for use by the functions being tested. */ setup(() => { - const instantiationService: TestInstantiationService = workbenchInstantiationService(undefined, disposables); + const instantiationService: TestInstantiationService = workbenchInstantiationService(undefined, disposables); linkDetector = instantiationService.createInstance(LinkDetector); }); diff --git a/src/vs/workbench/contrib/debug/test/browser/repl.test.ts b/src/vs/workbench/contrib/debug/test/browser/repl.test.ts index c0603a64412ee..f385cbbb7b3de 100644 --- a/src/vs/workbench/contrib/debug/test/browser/repl.test.ts +++ b/src/vs/workbench/contrib/debug/test/browser/repl.test.ts @@ -239,9 +239,9 @@ suite('Debug - REPL', () => { const repl = new ReplModel(configurationService); const replFilter = new ReplFilter(); - const getFilteredElements = () => { + const getFilteredElements = (): ReplOutputElement[] => { const elements = repl.getReplElements(); - return elements.filter(e => { + return elements.filter((e): e is ReplOutputElement => { const filterResult = replFilter.filter(e, TreeVisibility.Visible); return filterResult === true || filterResult === TreeVisibility.Visible; }); @@ -253,19 +253,19 @@ suite('Debug - REPL', () => { repl.appendToRepl(session, { output: 'fourth line\n', sev: severity.Info }); replFilter.filterQuery = 'first'; - const r1 = getFilteredElements(); + const r1 = getFilteredElements(); assert.strictEqual(r1.length, 1); assert.strictEqual(r1[0].value, 'first line\n'); replFilter.filterQuery = '!first'; - const r2 = getFilteredElements(); + const r2 = getFilteredElements(); assert.strictEqual(r1.length, 1); assert.strictEqual(r2[0].value, 'second line\n'); assert.strictEqual(r2[1].value, 'third line\n'); assert.strictEqual(r2[2].value, 'fourth line\n'); replFilter.filterQuery = 'first, line'; - const r3 = getFilteredElements(); + const r3 = getFilteredElements(); assert.strictEqual(r3.length, 4); assert.strictEqual(r3[0].value, 'first line\n'); assert.strictEqual(r3[1].value, 'second line\n'); @@ -273,22 +273,22 @@ suite('Debug - REPL', () => { assert.strictEqual(r3[3].value, 'fourth line\n'); replFilter.filterQuery = 'line, !second'; - const r4 = getFilteredElements(); + const r4 = getFilteredElements(); assert.strictEqual(r4.length, 3); assert.strictEqual(r4[0].value, 'first line\n'); assert.strictEqual(r4[1].value, 'third line\n'); assert.strictEqual(r4[2].value, 'fourth line\n'); replFilter.filterQuery = '!second, line'; - const r4_same = getFilteredElements(); + const r4_same = getFilteredElements(); assert.strictEqual(r4.length, r4_same.length); replFilter.filterQuery = '!line'; - const r5 = getFilteredElements(); + const r5 = getFilteredElements(); assert.strictEqual(r5.length, 0); replFilter.filterQuery = 'smth'; - const r6 = getFilteredElements(); + const r6 = getFilteredElements(); assert.strictEqual(r6.length, 0); }); }); diff --git a/src/vs/workbench/contrib/notebook/browser/controller/editActions.ts b/src/vs/workbench/contrib/notebook/browser/controller/editActions.ts index a7d5280085fde..c73973e433ee5 100644 --- a/src/vs/workbench/contrib/notebook/browser/controller/editActions.ts +++ b/src/vs/workbench/contrib/notebook/browser/controller/editActions.ts @@ -450,7 +450,7 @@ registerAction2(class ChangeCellLanguageAction extends NotebookCellAction{ + const item: ILanguagePickInput = { label: languageName, iconClasses: getIconClasses(modelService, languageService, this.getFakeResource(languageName, languageService)), description, diff --git a/src/vs/workbench/contrib/search/browser/searchModel.ts b/src/vs/workbench/contrib/search/browser/searchModel.ts index 97a018558d74d..8d982d4737e5b 100644 --- a/src/vs/workbench/contrib/search/browser/searchModel.ts +++ b/src/vs/workbench/contrib/search/browser/searchModel.ts @@ -2154,7 +2154,7 @@ export class SearchModel extends Disposable { const resolvedNotebookResults = await notebookResult.completeData; tokenSource.dispose(); const searchLength = Date.now() - searchStart; - const resolvedResult = { + const resolvedResult: ISearchComplete = { results: [...allClosedEditorResults.results, ...resolvedNotebookResults.results], messages: [...allClosedEditorResults.messages, ...resolvedNotebookResults.messages], limitHit: allClosedEditorResults.limitHit || resolvedNotebookResults.limitHit, diff --git a/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts b/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts index cd473790977de..1a02a11503320 100644 --- a/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts +++ b/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts @@ -1286,7 +1286,7 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer if (type === undefined) { return true; } - const settingValueMap: IStringDictionary = settingValue; + const settingValueMap: IStringDictionary = settingValue as any; return !settingValueMap[type]; } @@ -2574,7 +2574,7 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer private _handleError(err: any): void { let showOutput = true; if (err instanceof TaskError) { - const buildError = err; + const buildError = err; const needsConfig = buildError.code === TaskErrors.NotConfigured || buildError.code === TaskErrors.NoBuildTask || buildError.code === TaskErrors.NoTestTask; const needsTerminate = buildError.code === TaskErrors.RunningTask; if (needsConfig || needsTerminate) { @@ -2592,7 +2592,7 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer this._notificationService.notify({ severity: buildError.severity, message: buildError.message }); } } else if (err instanceof Error) { - const error = err; + const error = err; this._notificationService.error(error.message); showOutput = false; } else if (Types.isString(err)) { @@ -3404,7 +3404,7 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer })]); if (!timeout && ((await entries).length === 1) && this._configurationService.getValue(QUICKOPEN_SKIP_CONFIG)) { - const entry: any = ((await entries)[0]); + const entry: any = (await entries)[0]; if (entry.task) { this._handleSelection(entry); return; diff --git a/src/vs/workbench/services/configuration/test/browser/configurationEditing.test.ts b/src/vs/workbench/services/configuration/test/browser/configurationEditing.test.ts index 3056d9dec2665..31139bf5737cc 100644 --- a/src/vs/workbench/services/configuration/test/browser/configurationEditing.test.ts +++ b/src/vs/workbench/services/configuration/test/browser/configurationEditing.test.ts @@ -108,7 +108,7 @@ suite('ConfigurationEditing', () => { const workspaceFolder = joinPath(ROOT, uuid.generateUuid()); await fileService.createFolder(workspaceFolder); - instantiationService = workbenchInstantiationService(undefined, disposables); + instantiationService = workbenchInstantiationService(undefined, disposables); environmentService = TestEnvironmentService; environmentService.policyFile = joinPath(workspaceFolder, 'policies.json'); instantiationService.stub(IEnvironmentService, environmentService); 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 a7ef7154baa46..eab8d6064f58c 100644 --- a/src/vs/workbench/services/configuration/test/browser/configurationService.test.ts +++ b/src/vs/workbench/services/configuration/test/browser/configurationService.test.ts @@ -188,7 +188,7 @@ suite('WorkspaceContextService - Folder', () => { uriIdentityService, new NullLogService(), new NullPolicyService())); - await (testObject).initialize(convertToWorkspacePayload(folder)); + await testObject.initialize(convertToWorkspacePayload(folder)); const actual = testObject.getWorkspaceFolder(joinPath(folder, 'a').with({ query: 'myquery=1' })); @@ -228,7 +228,7 @@ suite('WorkspaceContextService - Workspace', () => { await fileService.createFolder(folderB); await fileService.writeFile(configResource, VSBuffer.fromString(JSON.stringify(workspace, null, '\t'))); - const instantiationService = workbenchInstantiationService(undefined, disposables); + const instantiationService = workbenchInstantiationService(undefined, disposables); const environmentService = TestEnvironmentService; const remoteAgentService = disposables.add(disposables.add(instantiationService.createInstance(RemoteAgentService))); instantiationService.stub(IRemoteAgentService, remoteAgentService); @@ -290,7 +290,7 @@ suite('WorkspaceContextService - Workspace Editing', () => { await fileService.createFolder(folderB); await fileService.writeFile(configResource, VSBuffer.fromString(JSON.stringify(workspace, null, '\t'))); - const instantiationService = workbenchInstantiationService(undefined, disposables); + const instantiationService = workbenchInstantiationService(undefined, disposables); const environmentService = TestEnvironmentService; const remoteAgentService = disposables.add(instantiationService.createInstance(RemoteAgentService)); instantiationService.stub(IRemoteAgentService, remoteAgentService); @@ -538,7 +538,7 @@ suite('WorkspaceService - Initialization', () => { await fileService.createFolder(folderB); await fileService.writeFile(configResource, VSBuffer.fromString(JSON.stringify(workspace, null, '\t'))); - const instantiationService = workbenchInstantiationService(undefined, disposables); + const instantiationService = workbenchInstantiationService(undefined, disposables); environmentService = TestEnvironmentService; const remoteAgentService = disposables.add(instantiationService.createInstance(RemoteAgentService)); instantiationService.stub(IRemoteAgentService, remoteAgentService); @@ -558,7 +558,7 @@ suite('WorkspaceService - Initialization', () => { await testObject.initialize({ id: '' }); instantiationService.stub(ITextFileService, disposables.add(instantiationService.createInstance(TestTextFileService))); - instantiationService.stub(ITextModelService, disposables.add(instantiationService.createInstance(TextModelResolverService))); + instantiationService.stub(ITextModelService, disposables.add(instantiationService.createInstance(TextModelResolverService))); testObject.acquireInstantiationService(instantiationService); }); @@ -800,7 +800,7 @@ suite('WorkspaceConfigurationService - Folder', () => { const folder = joinPath(ROOT, 'a'); await fileService.createFolder(folder); - instantiationService = workbenchInstantiationService(undefined, disposables); + instantiationService = workbenchInstantiationService(undefined, disposables); environmentService = TestEnvironmentService; environmentService.policyFile = joinPath(folder, 'policies.json'); const remoteAgentService = disposables.add(instantiationService.createInstance(RemoteAgentService)); @@ -1613,7 +1613,7 @@ suite('WorkspaceConfigurationService - Profiles', () => { const folder = joinPath(ROOT, 'a'); await fileService.createFolder(folder); - instantiationService = workbenchInstantiationService(undefined, disposables); + instantiationService = workbenchInstantiationService(undefined, disposables); environmentService = TestEnvironmentService; environmentService.policyFile = joinPath(folder, 'policies.json'); const remoteAgentService = disposables.add(instantiationService.createInstance(RemoteAgentService)); @@ -1637,7 +1637,7 @@ suite('WorkspaceConfigurationService - Profiles', () => { await workspaceService.initialize(convertToWorkspacePayload(folder)); instantiationService.stub(IKeybindingEditingService, disposables.add(instantiationService.createInstance(KeybindingsEditingService))); instantiationService.stub(ITextFileService, disposables.add(instantiationService.createInstance(TestTextFileService))); - instantiationService.stub(ITextModelService, disposables.add(instantiationService.createInstance(TextModelResolverService))); + instantiationService.stub(ITextModelService, disposables.add(instantiationService.createInstance(TextModelResolverService))); workspaceService.acquireInstantiationService(instantiationService); }); @@ -1968,7 +1968,7 @@ suite('WorkspaceConfigurationService-Multiroot', () => { await fileService.createFolder(folderB); await fileService.writeFile(configResource, VSBuffer.fromString(JSON.stringify(workspace, null, '\t'))); - const instantiationService = workbenchInstantiationService(undefined, disposables); + const instantiationService = workbenchInstantiationService(undefined, disposables); environmentService = TestEnvironmentService; const remoteAgentService = disposables.add(instantiationService.createInstance(RemoteAgentService)); instantiationService.stub(IRemoteAgentService, remoteAgentService); @@ -1990,7 +1990,7 @@ suite('WorkspaceConfigurationService-Multiroot', () => { await workspaceService.initialize(getWorkspaceIdentifier(configResource)); instantiationService.stub(IKeybindingEditingService, disposables.add(instantiationService.createInstance(KeybindingsEditingService))); instantiationService.stub(ITextFileService, disposables.add(instantiationService.createInstance(TestTextFileService))); - instantiationService.stub(ITextModelService, disposables.add(instantiationService.createInstance(TextModelResolverService))); + instantiationService.stub(ITextModelService, disposables.add(instantiationService.createInstance(TextModelResolverService))); jsonEditingServce = instantiationService.createInstance(JSONEditingService); instantiationService.stub(IJSONEditingService, jsonEditingServce); workspaceService.acquireInstantiationService(instantiationService); @@ -2709,7 +2709,7 @@ suite('WorkspaceConfigurationService - Remote Folder', () => { machineSettingsResource = joinPath(ROOT, 'machine-settings.json'); remoteSettingsResource = machineSettingsResource.with({ scheme: Schemas.vscodeRemote, authority: remoteAuthority }); - instantiationService = workbenchInstantiationService(undefined, disposables); + instantiationService = workbenchInstantiationService(undefined, disposables); environmentService = TestEnvironmentService; const remoteEnvironmentPromise = new Promise>(c => resolveRemoteEnvironment = () => c({ settingsPath: remoteSettingsResource })); const remoteAgentService = instantiationService.stub(IRemoteAgentService, >{ getEnvironment: () => remoteEnvironmentPromise }); diff --git a/src/vs/workbench/services/dialogs/test/electron-sandbox/fileDialogService.test.ts b/src/vs/workbench/services/dialogs/test/electron-sandbox/fileDialogService.test.ts index 45311b71c557f..5439e7be42f36 100644 --- a/src/vs/workbench/services/dialogs/test/electron-sandbox/fileDialogService.test.ts +++ b/src/vs/workbench/services/dialogs/test/electron-sandbox/fileDialogService.test.ts @@ -78,7 +78,7 @@ suite('FileDialogService', function () { const testFile: URI = URI.file('/test/file'); setup(async function () { - disposables.add(instantiationService = workbenchInstantiationService(undefined, disposables)); + disposables.add(instantiationService = workbenchInstantiationService(undefined, disposables)); const configurationService = new TestConfigurationService(); await configurationService.setUserConfiguration('files', { simpleDialog: { enable: true } }); instantiationService.stub(IConfigurationService, configurationService); diff --git a/src/vs/workbench/services/extensions/test/browser/extensionStorageMigration.test.ts b/src/vs/workbench/services/extensions/test/browser/extensionStorageMigration.test.ts index f1795ab490867..ae0a893194472 100644 --- a/src/vs/workbench/services/extensions/test/browser/extensionStorageMigration.test.ts +++ b/src/vs/workbench/services/extensions/test/browser/extensionStorageMigration.test.ts @@ -33,7 +33,7 @@ suite('ExtensionStorageMigration', () => { let instantiationService: TestInstantiationService; setup(() => { - instantiationService = workbenchInstantiationService(undefined, disposables); + instantiationService = workbenchInstantiationService(undefined, disposables); const fileService = disposables.add(new FileService(new NullLogService())); disposables.add(fileService.registerProvider(ROOT.scheme, disposables.add(new InMemoryFileSystemProvider()))); diff --git a/src/vs/workbench/services/search/test/common/searchHelpers.test.ts b/src/vs/workbench/services/search/test/common/searchHelpers.test.ts index 1e6c7670117dc..bc51969faef04 100644 --- a/src/vs/workbench/services/search/test/common/searchHelpers.test.ts +++ b/src/vs/workbench/services/search/test/common/searchHelpers.test.ts @@ -7,17 +7,17 @@ import * as assert from 'assert'; import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils'; import { Range } from 'vs/editor/common/core/range'; import { FindMatch, ITextModel } from 'vs/editor/common/model'; -import { ISearchRange, ITextQuery, ITextSearchContext, QueryType } from 'vs/workbench/services/search/common/search'; +import { ISearchRange, ITextQuery, ITextSearchContext, ITextSearchResult, QueryType } from 'vs/workbench/services/search/common/search'; import { getTextSearchMatchWithModelContext, editorMatchesToTextSearchResults } from 'vs/workbench/services/search/common/searchHelpers'; suite('SearchHelpers', () => { suite('editorMatchesToTextSearchResults', () => { ensureNoDisposablesAreLeakedInTestSuite(); - const mockTextModel: ITextModel = { + const mockTextModel = { getLineContent(lineNumber: number): string { return '' + lineNumber; } - }; + } as ITextModel; function assertRangesEqual(actual: ISearchRange | ISearchRange[], expected: ISearchRange[]) { if (!Array.isArray(actual)) { @@ -77,7 +77,7 @@ suite('SearchHelpers', () => { ensureNoDisposablesAreLeakedInTestSuite(); const MOCK_LINE_COUNT = 100; - const mockTextModel: ITextModel = { + const mockTextModel = { getLineContent(lineNumber: number): string { if (lineNumber < 1 || lineNumber > MOCK_LINE_COUNT) { throw new Error(`invalid line count: ${lineNumber}`); @@ -89,7 +89,7 @@ suite('SearchHelpers', () => { getLineCount(): number { return MOCK_LINE_COUNT; } - }; + } as ITextModel; function getQuery(beforeContext?: number, afterContext?: number): ITextQuery { return { @@ -123,20 +123,20 @@ suite('SearchHelpers', () => { }]; assert.deepStrictEqual(getTextSearchMatchWithModelContext(matches, mockTextModel, getQuery(1, 2)), [ - { + { text: '1', lineNumber: 1 }, ...matches, - { + { text: '3', lineNumber: 3 }, - { + { text: '4', lineNumber: 4 }, - ]); + ] satisfies ITextSearchResult[]); }); test('multiple matches next to each other', () => { diff --git a/src/vs/workbench/services/views/common/viewContainerModel.ts b/src/vs/workbench/services/views/common/viewContainerModel.ts index 60009d0ff794d..2aec0216c4b95 100644 --- a/src/vs/workbench/services/views/common/viewContainerModel.ts +++ b/src/vs/workbench/services/views/common/viewContainerModel.ts @@ -156,7 +156,7 @@ class ViewDescriptorsState extends Disposable { changedStates.push({ id, visible: !storedState.isHidden }); } } else { - const workspaceViewState = storedWorkspaceViewsStates[id]; + const workspaceViewState: IStoredWorkspaceViewState | undefined = storedWorkspaceViewsStates[id]; this.set(id, { active: false, visibleGlobal: !storedState.isHidden, @@ -256,7 +256,7 @@ class ViewDescriptorsState extends Disposable { } private parseStoredGlobalState(value: string): { state: Map; hasDuplicates: boolean } { - const storedValue = >JSON.parse(value); + const storedValue: Array = JSON.parse(value); let hasDuplicates = false; const state = storedValue.reduce((result, storedState) => { if (typeof storedState === 'string' /* migration */) { diff --git a/src/vs/workbench/services/views/test/browser/viewContainerModel.test.ts b/src/vs/workbench/services/views/test/browser/viewContainerModel.test.ts index 2a34154580b39..f37d4af42b73f 100644 --- a/src/vs/workbench/services/views/test/browser/viewContainerModel.test.ts +++ b/src/vs/workbench/services/views/test/browser/viewContainerModel.test.ts @@ -51,7 +51,7 @@ suite('ViewContainerModel', () => { let storageService: IStorageService; setup(() => { - const instantiationService: TestInstantiationService = workbenchInstantiationService(undefined, disposableStore); + const instantiationService: TestInstantiationService = workbenchInstantiationService(undefined, disposableStore); contextKeyService = disposableStore.add(instantiationService.createInstance(ContextKeyService)); instantiationService.stub(IContextKeyService, contextKeyService); storageService = instantiationService.get(IStorageService); diff --git a/src/vs/workbench/services/views/test/browser/viewDescriptorService.test.ts b/src/vs/workbench/services/views/test/browser/viewDescriptorService.test.ts index 58103b06c38cb..31b8bb8a6a335 100644 --- a/src/vs/workbench/services/views/test/browser/viewDescriptorService.test.ts +++ b/src/vs/workbench/services/views/test/browser/viewDescriptorService.test.ts @@ -31,7 +31,7 @@ suite('ViewDescriptorService', () => { let instantiationService: TestInstantiationService; setup(() => { - disposables.add(instantiationService = workbenchInstantiationService(undefined, disposables)); + disposables.add(instantiationService = workbenchInstantiationService(undefined, disposables)); instantiationService.stub(IContextKeyService, disposables.add(instantiationService.createInstance(ContextKeyService))); }); diff --git a/src/vs/workbench/test/browser/codeeditor.test.ts b/src/vs/workbench/test/browser/codeeditor.test.ts index 6bea2f87b2e2e..686bc17e88bec 100644 --- a/src/vs/workbench/test/browser/codeeditor.test.ts +++ b/src/vs/workbench/test/browser/codeeditor.test.ts @@ -39,7 +39,7 @@ suite('Editor - Range decorations', () => { setup(() => { disposables = new DisposableStore(); - instantiationService = workbenchInstantiationService(undefined, disposables); + instantiationService = workbenchInstantiationService(undefined, disposables); instantiationService.stub(IEditorService, new TestEditorService()); instantiationService.stub(ILanguageService, LanguageService); instantiationService.stub(IModelService, stubModelService(instantiationService)); From 4261ac866b587270d9da74fd4a0ff1f4c877c486 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 29 Apr 2024 10:08:31 -0700 Subject: [PATCH 087/104] Remove extra type assertions in main thread language features (#211651) Using `` can hide some common typing issues --- src/vs/editor/common/languages.ts | 4 +-- src/vs/monaco.d.ts | 2 +- .../api/browser/mainThreadLanguageFeatures.ts | 36 +++++++++---------- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/vs/editor/common/languages.ts b/src/vs/editor/common/languages.ts index 82fdcc21a7a2d..df179da3007bc 100644 --- a/src/vs/editor/common/languages.ts +++ b/src/vs/editor/common/languages.ts @@ -19,7 +19,7 @@ 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 { LanguageId } from 'vs/editor/common/encodedTokenAttributes'; -import { LanguageFilter } from 'vs/editor/common/languageSelector'; +import { LanguageSelector } from 'vs/editor/common/languageSelector'; import * as model from 'vs/editor/common/model'; import { TokenizationRegistry as TokenizationRegistryImpl } from 'vs/editor/common/tokenizationRegistry'; import { ContiguousMultilineTokens } from 'vs/editor/common/tokens/contiguousMultilineTokens'; @@ -1068,7 +1068,7 @@ export interface DocumentHighlightProvider { * A provider that can provide document highlights across multiple documents. */ export interface MultiDocumentHighlightProvider { - selector: LanguageFilter; + readonly selector: LanguageSelector; /** * Provide a Map of URI --> document highlights, like all occurrences of a variable or diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index 42bb190155a24..740d8f5f8e6ba 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -7395,7 +7395,7 @@ declare namespace monaco.languages { * A provider that can provide document highlights across multiple documents. */ export interface MultiDocumentHighlightProvider { - selector: LanguageFilter; + readonly selector: LanguageSelector; /** * Provide a Map of Uri --> document highlights, like all occurrences of a variable or * all exit-points of a function. diff --git a/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts b/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts index e956f7f056540..0253cba2d4e44 100644 --- a/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts +++ b/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts @@ -163,7 +163,7 @@ export class MainThreadLanguageFeatures extends Disposable implements MainThread // --- outline $registerDocumentSymbolProvider(handle: number, selector: IDocumentFilterDto[], displayName: string): void { - this._registrations.set(handle, this._languageFeaturesService.documentSymbolProvider.register(selector, { + this._registrations.set(handle, this._languageFeaturesService.documentSymbolProvider.register(selector, { displayName, provideDocumentSymbols: (model: ITextModel, token: CancellationToken): Promise => { return this._proxy.$provideDocumentSymbols(handle, model.uri, token); @@ -175,7 +175,7 @@ export class MainThreadLanguageFeatures extends Disposable implements MainThread $registerCodeLensSupport(handle: number, selector: IDocumentFilterDto[], eventHandle: number | undefined): void { - const provider = { + const provider: languages.CodeLensProvider = { provideCodeLenses: async (model: ITextModel, token: CancellationToken): Promise => { const listDto = await this._proxy.$provideCodeLenses(handle, model.uri, token); if (!listDto) { @@ -217,7 +217,7 @@ export class MainThreadLanguageFeatures extends Disposable implements MainThread // --- declaration $registerDefinitionSupport(handle: number, selector: IDocumentFilterDto[]): void { - this._registrations.set(handle, this._languageFeaturesService.definitionProvider.register(selector, { + this._registrations.set(handle, this._languageFeaturesService.definitionProvider.register(selector, { provideDefinition: (model, position, token): Promise => { return this._proxy.$provideDefinition(handle, model.uri, position, token).then(MainThreadLanguageFeatures._reviveLocationLinkDto); } @@ -225,7 +225,7 @@ export class MainThreadLanguageFeatures extends Disposable implements MainThread } $registerDeclarationSupport(handle: number, selector: IDocumentFilterDto[]): void { - this._registrations.set(handle, this._languageFeaturesService.declarationProvider.register(selector, { + this._registrations.set(handle, this._languageFeaturesService.declarationProvider.register(selector, { provideDeclaration: (model, position, token) => { return this._proxy.$provideDeclaration(handle, model.uri, position, token).then(MainThreadLanguageFeatures._reviveLocationLinkDto); } @@ -233,7 +233,7 @@ export class MainThreadLanguageFeatures extends Disposable implements MainThread } $registerImplementationSupport(handle: number, selector: IDocumentFilterDto[]): void { - this._registrations.set(handle, this._languageFeaturesService.implementationProvider.register(selector, { + this._registrations.set(handle, this._languageFeaturesService.implementationProvider.register(selector, { provideImplementation: (model, position, token): Promise => { return this._proxy.$provideImplementation(handle, model.uri, position, token).then(MainThreadLanguageFeatures._reviveLocationLinkDto); } @@ -241,7 +241,7 @@ export class MainThreadLanguageFeatures extends Disposable implements MainThread } $registerTypeDefinitionSupport(handle: number, selector: IDocumentFilterDto[]): void { - this._registrations.set(handle, this._languageFeaturesService.typeDefinitionProvider.register(selector, { + this._registrations.set(handle, this._languageFeaturesService.typeDefinitionProvider.register(selector, { provideTypeDefinition: (model, position, token): Promise => { return this._proxy.$provideTypeDefinition(handle, model.uri, position, token).then(MainThreadLanguageFeatures._reviveLocationLinkDto); } @@ -256,7 +256,7 @@ export class MainThreadLanguageFeatures extends Disposable implements MainThread this._proxy.$releaseHover(handle, hoverId); }); */ - this._registrations.set(handle, this._languageFeaturesService.hoverProvider.register(selector, >{ + this._registrations.set(handle, this._languageFeaturesService.hoverProvider.register(selector, { provideHover: async (model: ITextModel, position: EditorPosition, token: CancellationToken, context?: languages.HoverContext): Promise => { const serializedContext: languages.HoverContext<{ id: number }> = { verbosityRequest: context?.verbosityRequest ? { @@ -274,7 +274,7 @@ export class MainThreadLanguageFeatures extends Disposable implements MainThread // --- debug hover $registerEvaluatableExpressionProvider(handle: number, selector: IDocumentFilterDto[]): void { - this._registrations.set(handle, this._languageFeaturesService.evaluatableExpressionProvider.register(selector, { + this._registrations.set(handle, this._languageFeaturesService.evaluatableExpressionProvider.register(selector, { provideEvaluatableExpression: (model: ITextModel, position: EditorPosition, token: CancellationToken): Promise => { return this._proxy.$provideEvaluatableExpression(handle, model.uri, position, token); } @@ -284,7 +284,7 @@ export class MainThreadLanguageFeatures extends Disposable implements MainThread // --- inline values $registerInlineValuesProvider(handle: number, selector: IDocumentFilterDto[], eventHandle: number | undefined): void { - const provider = { + const provider: languages.InlineValuesProvider = { provideInlineValues: (model: ITextModel, viewPort: EditorRange, context: languages.InlineValueContext, token: CancellationToken): Promise => { return this._proxy.$provideInlineValues(handle, model.uri, viewPort, context, token); } @@ -309,7 +309,7 @@ export class MainThreadLanguageFeatures extends Disposable implements MainThread // --- occurrences $registerDocumentHighlightProvider(handle: number, selector: IDocumentFilterDto[]): void { - this._registrations.set(handle, this._languageFeaturesService.documentHighlightProvider.register(selector, { + this._registrations.set(handle, this._languageFeaturesService.documentHighlightProvider.register(selector, { provideDocumentHighlights: (model: ITextModel, position: EditorPosition, token: CancellationToken): Promise => { return this._proxy.$provideDocumentHighlights(handle, model.uri, position, token); } @@ -317,7 +317,7 @@ export class MainThreadLanguageFeatures extends Disposable implements MainThread } $registerMultiDocumentHighlightProvider(handle: number, selector: IDocumentFilterDto[]): void { - this._registrations.set(handle, this._languageFeaturesService.multiDocumentHighlightProvider.register(selector, { + this._registrations.set(handle, this._languageFeaturesService.multiDocumentHighlightProvider.register(selector, { selector: selector, provideMultiDocumentHighlights: (model: ITextModel, position: EditorPosition, otherModels: ITextModel[], token: CancellationToken): Promise | undefined> => { return this._proxy.$provideMultiDocumentHighlights(handle, model.uri, position, otherModels.map(model => model.uri), token).then(dto => { @@ -343,7 +343,7 @@ export class MainThreadLanguageFeatures extends Disposable implements MainThread // --- linked editing $registerLinkedEditingRangeProvider(handle: number, selector: IDocumentFilterDto[]): void { - this._registrations.set(handle, this._languageFeaturesService.linkedEditingRangeProvider.register(selector, { + this._registrations.set(handle, this._languageFeaturesService.linkedEditingRangeProvider.register(selector, { provideLinkedEditingRanges: async (model: ITextModel, position: EditorPosition, token: CancellationToken): Promise => { const res = await this._proxy.$provideLinkedEditingRanges(handle, model.uri, position, token); if (res) { @@ -360,7 +360,7 @@ export class MainThreadLanguageFeatures extends Disposable implements MainThread // --- references $registerReferenceSupport(handle: number, selector: IDocumentFilterDto[]): void { - this._registrations.set(handle, this._languageFeaturesService.referenceProvider.register(selector, { + this._registrations.set(handle, this._languageFeaturesService.referenceProvider.register(selector, { provideReferences: (model: ITextModel, position: EditorPosition, context: languages.ReferenceContext, token: CancellationToken): Promise => { return this._proxy.$provideReferences(handle, model.uri, position, context, token).then(MainThreadLanguageFeatures._reviveLocationDto); } @@ -376,7 +376,7 @@ export class MainThreadLanguageFeatures extends Disposable implements MainThread if (!listDto) { return undefined; } - return { + return { actions: MainThreadLanguageFeatures._reviveCodeActionDto(listDto.actions, this._uriIdentService), dispose: () => { if (typeof listDto.cacheId === 'number') { @@ -649,7 +649,7 @@ export class MainThreadLanguageFeatures extends Disposable implements MainThread // --- parameter hints $registerSignatureHelpProvider(handle: number, selector: IDocumentFilterDto[], metadata: ISignatureHelpProviderMetadataDto): void { - this._registrations.set(handle, this._languageFeaturesService.signatureHelpProvider.register(selector, { + this._registrations.set(handle, this._languageFeaturesService.signatureHelpProvider.register(selector, { signatureHelpTriggerCharacters: metadata.triggerCharacters, signatureHelpRetriggerCharacters: metadata.retriggerCharacters, @@ -672,7 +672,7 @@ export class MainThreadLanguageFeatures extends Disposable implements MainThread // --- inline hints $registerInlayHintsProvider(handle: number, selector: IDocumentFilterDto[], supportsResolve: boolean, eventHandle: number | undefined, displayName: string | undefined): void { - const provider = { + const provider: languages.InlayHintsProvider = { displayName, provideInlayHints: async (model: ITextModel, range: EditorRange, token: CancellationToken): Promise => { const result = await this._proxy.$provideInlayHints(handle, model.uri, range, token); @@ -764,7 +764,7 @@ export class MainThreadLanguageFeatures extends Disposable implements MainThread $registerDocumentColorProvider(handle: number, selector: IDocumentFilterDto[]): void { const proxy = this._proxy; - this._registrations.set(handle, this._languageFeaturesService.colorProvider.register(selector, { + this._registrations.set(handle, this._languageFeaturesService.colorProvider.register(selector, { provideDocumentColors: (model, token) => { return proxy.$provideDocumentColors(handle, model.uri, token) .then(documentColors => { @@ -797,7 +797,7 @@ export class MainThreadLanguageFeatures extends Disposable implements MainThread // --- folding $registerFoldingRangeProvider(handle: number, selector: IDocumentFilterDto[], extensionId: ExtensionIdentifier, eventHandle: number | undefined): void { - const provider = { + const provider: languages.FoldingRangeProvider = { id: extensionId.value, provideFoldingRanges: (model, context, token) => { return this._proxy.$provideFoldingRanges(handle, model.uri, context, token); From b45d1a1f166daf8591a496748787caf7c9cef39d Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 29 Apr 2024 10:09:10 -0700 Subject: [PATCH 088/104] Switch to standard `.flat()` (#211653) --- src/vs/base/common/arrays.ts | 7 ----- src/vs/workbench/common/views.ts | 3 +-- .../browser/debugConfigurationManager.ts | 4 +-- .../extensions/browser/extensionsActions.ts | 3 +-- .../extensions/browser/extensionsViews.ts | 10 +++---- .../browser/workspaceRecommendations.ts | 4 +-- .../extensions/common/extensionQuery.ts | 26 +++++++++--------- .../contrib/markers/browser/markersModel.ts | 4 +-- .../contrib/scm/browser/scmViewPane.ts | 3 +-- .../browser/searchEditorSerialization.ts | 9 +++---- .../browser/gettingStarted.ts | 8 +++--- .../browser/gettingStartedService.ts | 8 +++--- .../editor/browser/editorResolverService.ts | 4 +-- .../common/workspaceExtensionsConfig.ts | 6 ++--- .../preferences/common/preferencesModels.ts | 27 +++++++++---------- .../services/remote/common/tunnelModel.ts | 5 ++-- .../services/search/common/queryBuilder.ts | 4 +-- .../services/search/common/searchService.ts | 4 +-- .../search/common/textSearchManager.ts | 6 ++--- 19 files changed, 65 insertions(+), 80 deletions(-) diff --git a/src/vs/base/common/arrays.ts b/src/vs/base/common/arrays.ts index a0a169b7f9f32..52e542c0eb80b 100644 --- a/src/vs/base/common/arrays.ts +++ b/src/vs/base/common/arrays.ts @@ -435,13 +435,6 @@ export function commonPrefixLength(one: ReadonlyArray, other: ReadonlyArra return result; } -/** - * @deprecated Use `[].flat()` - */ -export function flatten(arr: T[][]): T[] { - return ([]).concat(...arr); -} - export function range(to: number): number[]; export function range(from: number, to: number): number[]; export function range(arg: number, to?: number): number[] { diff --git a/src/vs/workbench/common/views.ts b/src/vs/workbench/common/views.ts index 9703c105d0e7e..7d0bb72c307a7 100644 --- a/src/vs/workbench/common/views.ts +++ b/src/vs/workbench/common/views.ts @@ -15,7 +15,6 @@ import { getOrSet, SetMap } from 'vs/base/common/map'; import { Registry } from 'vs/platform/registry/common/platform'; import { IKeybindings } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; -import { flatten } from 'vs/base/common/arrays'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { IProgressIndicator } from 'vs/platform/progress/common/progress'; import Severity from 'vs/base/common/severity'; @@ -204,7 +203,7 @@ class ViewContainersRegistryImpl extends Disposable implements IViewContainersRe private readonly defaultViewContainers: ViewContainer[] = []; get all(): ViewContainer[] { - return flatten([...this.viewContainers.values()]); + return [...this.viewContainers.values()].flat(); } registerViewContainer(viewContainerDescriptor: IViewContainerDescriptor, viewContainerLocation: ViewContainerLocation, options?: { isDefault?: boolean; doNotRegisterOpenCommand?: boolean }): ViewContainer { diff --git a/src/vs/workbench/contrib/debug/browser/debugConfigurationManager.ts b/src/vs/workbench/contrib/debug/browser/debugConfigurationManager.ts index 87d153a08df77..7151a0ffa5d01 100644 --- a/src/vs/workbench/contrib/debug/browser/debugConfigurationManager.ts +++ b/src/vs/workbench/contrib/debug/browser/debugConfigurationManager.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { distinct, flatten } from 'vs/base/common/arrays'; +import { distinct } from 'vs/base/common/arrays'; import { sequence } from 'vs/base/common/async'; import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation'; import { Emitter, Event } from 'vs/base/common/event'; @@ -258,7 +258,7 @@ export class ConfigurationManager implements IConfigurationManager { }); const nestedPicks = await Promise.all(picks); - const items = flatten(nestedPicks); + const items = nestedPicks.flat(); input.items = items; input.busy = false; diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts b/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts index f5144870fa71d..1fd2e6152b3fb 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts @@ -63,7 +63,6 @@ import { isVirtualWorkspace } from 'vs/platform/workspace/common/virtualWorkspac import { escapeMarkdownSyntaxTokens, IMarkdownString, MarkdownString } from 'vs/base/common/htmlContent'; import { IPaneCompositePartService } from 'vs/workbench/services/panecomposite/browser/panecomposite'; import { ViewContainerLocation } from 'vs/workbench/common/views'; -import { flatten } from 'vs/base/common/arrays'; import { fromNow } from 'vs/base/common/date'; import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences'; import { getLocale } from 'vs/platform/languagePacks/common/languagePacks'; @@ -251,7 +250,7 @@ export class ActionWithDropDownAction extends ExtensionAction { private readonly actionsGroups: ExtensionAction[][], ) { super(id, label); - this.extensionActions = flatten(actionsGroups); + this.extensionActions = actionsGroups.flat(); this.update(); this._register(Event.any(...this.extensionActions.map(a => a.onDidChange))(() => this.update(true))); this.extensionActions.forEach(a => this._register(a)); diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsViews.ts b/src/vs/workbench/contrib/extensions/browser/extensionsViews.ts index f6451dd55c0b5..6b0e7319bc160 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsViews.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsViews.ts @@ -31,7 +31,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; import { ViewPane, IViewPaneOptions, ViewPaneShowActions } from 'vs/workbench/browser/parts/views/viewPane'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; -import { coalesce, distinct, flatten } from 'vs/base/common/arrays'; +import { coalesce, distinct } from 'vs/base/common/arrays'; import { alert } from 'vs/base/browser/ui/aria/aria'; import { IListContextMenuEvent } from 'vs/base/browser/ui/list/list'; import { CancellationToken } from 'vs/base/common/cancellation'; @@ -978,12 +978,12 @@ export class ExtensionsListView extends ViewPane { .map(extensionId => isString(extensionId) ? extensionId.toLowerCase() : extensionId); return distinct( - flatten(await Promise.all([ + (await Promise.all([ // Order is important this.extensionRecommendationsService.getImportantRecommendations(), this.extensionRecommendationsService.getFileBasedRecommendations(), this.extensionRecommendationsService.getOtherRecommendations() - ])).filter(extensionId => !local.includes(extensionId.toLowerCase()) && !workspaceRecommendations.includes(extensionId.toLowerCase()) + ])).flat().filter(extensionId => !local.includes(extensionId.toLowerCase()) && !workspaceRecommendations.includes(extensionId.toLowerCase()) ), extensionId => extensionId.toLowerCase()); } @@ -993,13 +993,13 @@ export class ExtensionsListView extends ViewPane { const localExtensionIds = localExtensions.map(e => e.identifier.id.toLowerCase()); const allRecommendations = distinct( - flatten(await Promise.all([ + (await Promise.all([ // Order is important this.getWorkspaceRecommendations(), this.extensionRecommendationsService.getImportantRecommendations(), this.extensionRecommendationsService.getFileBasedRecommendations(), this.extensionRecommendationsService.getOtherRecommendations() - ])).filter(extensionId => { + ])).flat().filter(extensionId => { if (isString(extensionId)) { return !localExtensionIds.includes(extensionId.toLowerCase()); } diff --git a/src/vs/workbench/contrib/extensions/browser/workspaceRecommendations.ts b/src/vs/workbench/contrib/extensions/browser/workspaceRecommendations.ts index eda5f43eac0ba..586c9f83b2f09 100644 --- a/src/vs/workbench/contrib/extensions/browser/workspaceRecommendations.ts +++ b/src/vs/workbench/contrib/extensions/browser/workspaceRecommendations.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { EXTENSION_IDENTIFIER_PATTERN } from 'vs/platform/extensionManagement/common/extensionManagement'; -import { distinct, equals, flatten } from 'vs/base/common/arrays'; +import { distinct, equals } from 'vs/base/common/arrays'; import { ExtensionRecommendations, ExtensionRecommendation } from 'vs/workbench/contrib/extensions/browser/extensionRecommendations'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { ExtensionRecommendationReason } from 'vs/workbench/services/extensionRecommendations/common/extensionRecommendations'; @@ -150,7 +150,7 @@ export class WorkspaceRecommendations extends ExtensionRecommendations { const invalidExtensions: string[] = []; let message = ''; - const allRecommendations = distinct(flatten(contents.map(({ recommendations }) => recommendations || []))); + const allRecommendations = distinct(contents.flatMap(({ recommendations }) => recommendations || [])); const regEx = new RegExp(EXTENSION_IDENTIFIER_PATTERN); for (const extensionId of allRecommendations) { if (regEx.test(extensionId)) { diff --git a/src/vs/workbench/contrib/extensions/common/extensionQuery.ts b/src/vs/workbench/contrib/extensions/common/extensionQuery.ts index b74676a210ff4..d916401a6a713 100644 --- a/src/vs/workbench/contrib/extensions/common/extensionQuery.ts +++ b/src/vs/workbench/contrib/extensions/common/extensionQuery.ts @@ -3,7 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { flatten } from 'vs/base/common/arrays'; import { EXTENSION_CATEGORIES } from 'vs/platform/extensions/common/extensions'; export class Query { @@ -26,19 +25,18 @@ export class Query { const hasSort = subcommands.sort.some(subcommand => queryContains(`@sort:${subcommand}`)); const hasCategory = subcommands.category.some(subcommand => queryContains(`@category:${subcommand}`)); - return flatten( - commands.map(command => { - if (hasSort && command === 'sort' || hasCategory && command === 'category') { - return []; - } - if (command in subcommands) { - return (subcommands as Record)[command] - .map(subcommand => `@${command}:${subcommand}${subcommand === '' ? '' : ' '}`); - } - else { - return queryContains(`@${command}`) ? [] : [`@${command} `]; - } - })); + return commands.flatMap(command => { + if (hasSort && command === 'sort' || hasCategory && command === 'category') { + return []; + } + if (command in subcommands) { + return (subcommands as Record)[command] + .map(subcommand => `@${command}:${subcommand}${subcommand === '' ? '' : ' '}`); + } + else { + return queryContains(`@${command}`) ? [] : [`@${command} `]; + } + }); } static parse(value: string): Query { diff --git a/src/vs/workbench/contrib/markers/browser/markersModel.ts b/src/vs/workbench/contrib/markers/browser/markersModel.ts index ad0e29114f2db..0e4fbdfb8024f 100644 --- a/src/vs/workbench/contrib/markers/browser/markersModel.ts +++ b/src/vs/workbench/contrib/markers/browser/markersModel.ts @@ -7,7 +7,7 @@ import { basename, extUri } from 'vs/base/common/resources'; import { URI } from 'vs/base/common/uri'; import { Range, IRange } from 'vs/editor/common/core/range'; import { IMarker, MarkerSeverity, IRelatedInformation, IMarkerData } from 'vs/platform/markers/common/markers'; -import { isNonEmptyArray, flatten } from 'vs/base/common/arrays'; +import { isNonEmptyArray } from 'vs/base/common/arrays'; import { ResourceMap } from 'vs/base/common/map'; import { Emitter, Event } from 'vs/base/common/event'; import { Hasher } from 'vs/base/common/hash'; @@ -52,7 +52,7 @@ export class ResourceMarkers { get markers(): readonly Marker[] { if (!this._cachedMarkers) { - this._cachedMarkers = flatten([...this._markersMap.values()]).sort(ResourceMarkers._compareMarkers); + this._cachedMarkers = [...this._markersMap.values()].flat().sort(ResourceMarkers._compareMarkers); } return this._cachedMarkers; } diff --git a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts index 7ffaa617d4ab3..bdff99acf7988 100644 --- a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts +++ b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts @@ -39,7 +39,6 @@ import { compareFileNames, comparePaths } from 'vs/base/common/comparers'; import { FuzzyScore, createMatches, IMatch } from 'vs/base/common/filters'; import { IViewDescriptorService, ViewContainerLocation } from 'vs/workbench/common/views'; import { localize } from 'vs/nls'; -import { flatten } from 'vs/base/common/arrays'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { EditorResourceAccessor, SideBySideEditor } from 'vs/workbench/common/editor'; import { SIDE_BAR_BACKGROUND, PANEL_BACKGROUND } from 'vs/workbench/common/theme'; @@ -589,7 +588,7 @@ class RepositoryPaneActionRunner extends ActionRunner { const selection = this.getSelectedResources(); const contextIsSelected = selection.some(s => s === context); const actualContext = contextIsSelected ? selection : [context]; - const args = flatten(actualContext.map(e => ResourceTree.isResourceNode(e) ? ResourceTree.collect(e) : [e])); + const args = actualContext.map(e => ResourceTree.isResourceNode(e) ? ResourceTree.collect(e) : [e]).flat(); await action.run(...args); } } diff --git a/src/vs/workbench/contrib/searchEditor/browser/searchEditorSerialization.ts b/src/vs/workbench/contrib/searchEditor/browser/searchEditorSerialization.ts index c017b2db0eda8..62bbb3386a52f 100644 --- a/src/vs/workbench/contrib/searchEditor/browser/searchEditorSerialization.ts +++ b/src/vs/workbench/contrib/searchEditor/browser/searchEditorSerialization.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { coalesce, flatten } from 'vs/base/common/arrays'; +import { coalesce } from 'vs/base/common/arrays'; import { URI } from 'vs/base/common/uri'; import 'vs/css!./media/searchEditor'; import { ServicesAccessor } from 'vs/editor/browser/editorExtensions'; @@ -255,10 +255,9 @@ export const serializeSearchResultForEditor = const allResults = flattenSearchResultSerializations( - flatten( - searchResult.folderMatches().sort(matchComparer) - .map(folderMatch => folderMatch.allDownstreamFileMatches().sort(matchComparer) - .flatMap(fileMatch => fileMatchToSearchResultFormat(fileMatch, labelFormatter))))); + searchResult.folderMatches().sort(matchComparer) + .map(folderMatch => folderMatch.allDownstreamFileMatches().sort(matchComparer) + .flatMap(fileMatch => fileMatchToSearchResultFormat(fileMatch, labelFormatter))).flat()); return { matchRanges: allResults.matchRanges.map(translateRangeLines(info.length)), diff --git a/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStarted.ts b/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStarted.ts index 147ad6fc7cc8b..1d374e644c3c0 100644 --- a/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStarted.ts +++ b/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStarted.ts @@ -10,7 +10,7 @@ import { Button } from 'vs/base/browser/ui/button/button'; import { renderLabelWithIcons } from 'vs/base/browser/ui/iconLabel/iconLabels'; import { DomScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement'; import { Toggle } from 'vs/base/browser/ui/toggle/toggle'; -import { coalesce, equals, flatten } from 'vs/base/common/arrays'; +import { coalesce, equals } from 'vs/base/common/arrays'; import { Delayer, Throttler } from 'vs/base/common/async'; import { CancellationToken } from 'vs/base/common/cancellation'; import { Codicon } from 'vs/base/common/codicons'; @@ -570,7 +570,7 @@ export class GettingStartedPage extends EditorPane { this.updateMediaSourceForColorMode(mediaElement, media.path); this.stepDisposables.add(addDisposableListener(this.stepMediaComponent, 'click', () => { - const hrefs = flatten(stepToExpand.description.map(lt => lt.nodes.filter((node): node is ILink => typeof node !== 'string').map(node => node.href))); + const hrefs = stepToExpand.description.map(lt => lt.nodes.filter((node): node is ILink => typeof node !== 'string').map(node => node.href)).flat(); if (hrefs.length === 1) { const href = hrefs[0]; if (href.startsWith('http')) { @@ -602,7 +602,7 @@ export class GettingStartedPage extends EditorPane { })); this.stepDisposables.add(addDisposableListener(this.stepMediaComponent, 'click', () => { - const hrefs = flatten(stepToExpand.description.map(lt => lt.nodes.filter((node): node is ILink => typeof node !== 'string').map(node => node.href))); + const hrefs = stepToExpand.description.map(lt => lt.nodes.filter((node): node is ILink => typeof node !== 'string').map(node => node.href)).flat(); if (hrefs.length === 1) { const href = hrefs[0]; if (href.startsWith('http')) { @@ -644,7 +644,7 @@ export class GettingStartedPage extends EditorPane { if (serializedContextKeyExprs) { const contextKeyExprs = coalesce(serializedContextKeyExprs.map(expr => ContextKeyExpr.deserialize(expr))); - const watchingKeys = new Set(flatten(contextKeyExprs.map(expr => expr.keys()))); + const watchingKeys = new Set(contextKeyExprs.flatMap(expr => expr.keys())); this.stepDisposables.add(this.contextService.onDidChangeContext(e => { if (e.affectsSome(watchingKeys)) { postTrueKeysMessage(); } diff --git a/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStartedService.ts b/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStartedService.ts index db46c01330b3c..d70c6800b7784 100644 --- a/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStartedService.ts +++ b/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStartedService.ts @@ -26,7 +26,7 @@ import { ILink, LinkedText, parseLinkedText } from 'vs/base/common/linkedText'; import { walkthroughsExtensionPoint } from 'vs/workbench/contrib/welcomeGettingStarted/browser/gettingStartedExtensionPoint'; import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { dirname } from 'vs/base/common/path'; -import { coalesce, flatten } from 'vs/base/common/arrays'; +import { coalesce } from 'vs/base/common/arrays'; import { IViewsService } from 'vs/workbench/services/views/common/viewsService'; import { localize, localize2 } from 'vs/nls'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; @@ -567,10 +567,10 @@ export class WalkthroughsService extends Disposable implements IWalkthroughsServ } if (!step.completionEvents.length) { - step.completionEvents = coalesce(flatten( + step.completionEvents = coalesce( step.description .filter(linkedText => linkedText.nodes.length === 1) // only buttons - .map(linkedText => + .flatMap(linkedText => linkedText.nodes .filter(((node): node is ILink => typeof node !== 'string')) .map(({ href }) => { @@ -581,7 +581,7 @@ export class WalkthroughsService extends Disposable implements IWalkthroughsServ return 'onLink:' + href; } return undefined; - })))); + }))); } if (!step.completionEvents.length) { diff --git a/src/vs/workbench/services/editor/browser/editorResolverService.ts b/src/vs/workbench/services/editor/browser/editorResolverService.ts index d18ee039799a7..8275646f62eb0 100644 --- a/src/vs/workbench/services/editor/browser/editorResolverService.ts +++ b/src/vs/workbench/services/editor/browser/editorResolverService.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as glob from 'vs/base/common/glob'; -import { distinct, firstOrDefault, flatten, insert } from 'vs/base/common/arrays'; +import { distinct, firstOrDefault, insert } from 'vs/base/common/arrays'; import { Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { basename, extname, isEqual } from 'vs/base/common/resources'; import { URI } from 'vs/base/common/uri'; @@ -339,7 +339,7 @@ export class EditorResolverService extends Disposable implements IEditorResolver * Returns all editors as an array. Possible to contain duplicates */ private get _registeredEditors(): RegisteredEditors { - return flatten(Array.from(this._flattenedEditors.values())); + return Array.from(this._flattenedEditors.values()).flat(); } updateUserAssociations(globPattern: string, editorID: string): void { diff --git a/src/vs/workbench/services/extensionRecommendations/common/workspaceExtensionsConfig.ts b/src/vs/workbench/services/extensionRecommendations/common/workspaceExtensionsConfig.ts index e1b6f5880f881..2b6fecc8eaf41 100644 --- a/src/vs/workbench/services/extensionRecommendations/common/workspaceExtensionsConfig.ts +++ b/src/vs/workbench/services/extensionRecommendations/common/workspaceExtensionsConfig.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { distinct, flatten } from 'vs/base/common/arrays'; +import { distinct } from 'vs/base/common/arrays'; import { Emitter, Event } from 'vs/base/common/event'; import { JSONPath, parse } from 'vs/base/common/json'; import { Disposable } from 'vs/base/common/lifecycle'; @@ -81,12 +81,12 @@ export class WorkspaceExtensionsConfigService extends Disposable implements IWor async getRecommendations(): Promise { const configs = await this.getExtensionsConfigs(); - return distinct(flatten(configs.map(c => c.recommendations ? c.recommendations.map(c => c.toLowerCase()) : []))); + return distinct(configs.flatMap(c => c.recommendations ? c.recommendations.map(c => c.toLowerCase()) : [])); } async getUnwantedRecommendations(): Promise { const configs = await this.getExtensionsConfigs(); - return distinct(flatten(configs.map(c => c.unwantedRecommendations ? c.unwantedRecommendations.map(c => c.toLowerCase()) : []))); + return distinct(configs.flatMap(c => c.unwantedRecommendations ? c.unwantedRecommendations.map(c => c.toLowerCase()) : [])); } async toggleRecommendation(extensionId: string): Promise { diff --git a/src/vs/workbench/services/preferences/common/preferencesModels.ts b/src/vs/workbench/services/preferences/common/preferencesModels.ts index f0c0b5ca0f1c1..507844e02c8ac 100644 --- a/src/vs/workbench/services/preferences/common/preferencesModels.ts +++ b/src/vs/workbench/services/preferences/common/preferencesModels.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { flatten, tail, coalesce } from 'vs/base/common/arrays'; +import { tail, coalesce } from 'vs/base/common/arrays'; import { IStringDictionary } from 'vs/base/common/collections'; import { Emitter, Event } from 'vs/base/common/event'; import { JSONVisitor, visit } from 'vs/base/common/json'; @@ -900,19 +900,18 @@ export class DefaultSettingsEditorModel extends AbstractSettingsModel implements builder.pushGroup(settingsGroup); // builder has rewritten settings ranges, fix match ranges - const fixedMatches = flatten( - filterMatches - .map(m => m.matches || []) - .map((settingMatches, i) => { - const setting = settingsGroup.sections[0].settings[i]; - return settingMatches.map(range => { - return new Range( - range.startLineNumber + setting.range.startLineNumber, - range.startColumn, - range.endLineNumber + setting.range.startLineNumber, - range.endColumn); - }); - })); + const fixedMatches = filterMatches + .map(m => m.matches || []) + .flatMap((settingMatches, i) => { + const setting = settingsGroup.sections[0].settings[i]; + return settingMatches.map(range => { + return new Range( + range.startLineNumber + setting.range.startLineNumber, + range.startColumn, + range.endLineNumber + setting.range.startLineNumber, + range.endColumn); + }); + }); return fixedMatches; } diff --git a/src/vs/workbench/services/remote/common/tunnelModel.ts b/src/vs/workbench/services/remote/common/tunnelModel.ts index f0ceaf1950c32..14f20e126ad98 100644 --- a/src/vs/workbench/services/remote/common/tunnelModel.ts +++ b/src/vs/workbench/services/remote/common/tunnelModel.ts @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ import * as nls from 'vs/nls'; -import { flatten } from 'vs/base/common/arrays'; import { debounce } from 'vs/base/common/decorators'; import { Emitter, Event } from 'vs/base/common/event'; import { hash } from 'vs/base/common/hash'; @@ -988,14 +987,14 @@ export class TunnelModel extends Disposable { } // Group calls to provide attributes by pid. - const allProviderResults = await Promise.all(flatten(this.portAttributesProviders.map(provider => { + const allProviderResults = await Promise.all(this.portAttributesProviders.flatMap(provider => { return Array.from(pidToPortsMapping.entries()).map(entry => { const portGroup = entry[1]; const matchingCandidate = matchingCandidates.get(portGroup[0]); return provider.providePortAttributes(portGroup, matchingCandidate?.pid, matchingCandidate?.detail, CancellationToken.None); }); - }))); + })); const providedAttributes: Map = new Map(); allProviderResults.forEach(attributes => attributes.forEach(attribute => { if (attribute) { diff --git a/src/vs/workbench/services/search/common/queryBuilder.ts b/src/vs/workbench/services/search/common/queryBuilder.ts index 9124249957aa6..9259afa1d89c6 100644 --- a/src/vs/workbench/services/search/common/queryBuilder.ts +++ b/src/vs/workbench/services/search/common/queryBuilder.ts @@ -228,7 +228,7 @@ export class QueryBuilder { }; if (options.onlyOpenEditors) { - const openEditors = arrays.coalesce(arrays.flatten(this.editorGroupsService.groups.map(group => group.editors.map(editor => editor.resource)))); + const openEditors = arrays.coalesce(this.editorGroupsService.groups.flatMap(group => group.editors.map(editor => editor.resource))); this.logService.trace('QueryBuilder#commonQuery - openEditor URIs', JSON.stringify(openEditors)); const openEditorsInQuery = openEditors.filter(editor => pathIncludedInQuery(queryProps, editor.fsPath)); const openEditorsQueryProps = this.commonQueryFromFileList(openEditorsInQuery); @@ -358,7 +358,7 @@ export class QueryBuilder { result.searchPaths = searchPaths; } - const exprSegments = arrays.flatten(expandedExprSegments); + const exprSegments = expandedExprSegments.flat(); const includePattern = patternListToIExpression(...exprSegments); if (includePattern) { result.pattern = includePattern; diff --git a/src/vs/workbench/services/search/common/searchService.ts b/src/vs/workbench/services/search/common/searchService.ts index 8d97feed7b330..cec7fb1114ce5 100644 --- a/src/vs/workbench/services/search/common/searchService.ts +++ b/src/vs/workbench/services/search/common/searchService.ts @@ -202,8 +202,8 @@ export class SearchService extends Disposable implements ISearchService { return { limitHit: completes[0] && completes[0].limitHit, stats: completes[0].stats, - messages: arrays.coalesce(arrays.flatten(completes.map(i => i.messages))).filter(arrays.uniqueFilter(message => message.type + message.text + message.trusted)), - results: arrays.flatten(completes.map((c: ISearchComplete) => c.results)) + messages: arrays.coalesce(completes.flatMap(i => i.messages)).filter(arrays.uniqueFilter(message => message.type + message.text + message.trusted)), + results: completes.flatMap((c: ISearchComplete) => c.results) }; })(); diff --git a/src/vs/workbench/services/search/common/textSearchManager.ts b/src/vs/workbench/services/search/common/textSearchManager.ts index eb83a7ae27ee7..84808af5691ec 100644 --- a/src/vs/workbench/services/search/common/textSearchManager.ts +++ b/src/vs/workbench/services/search/common/textSearchManager.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { flatten, mapArrayOrNot } from 'vs/base/common/arrays'; +import { mapArrayOrNot } from 'vs/base/common/arrays'; import { isThenable } from 'vs/base/common/async'; import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation'; import { toErrorMessage } from 'vs/base/common/errorMessage'; @@ -81,11 +81,11 @@ export class TextSearchManager { const someFolderHitLImit = results.some(result => !!result && !!result.limitHit); resolve({ limitHit: this.isLimitHit || someFolderHitLImit, - messages: flatten(results.map(result => { + messages: results.flatMap(result => { if (!result?.message) { return []; } if (Array.isArray(result.message)) { return result.message; } else { return [result.message]; } - })), + }), stats: { type: this.processType } From bb6fe3b1eb407cc6303b0d7e574c905f56250e7f Mon Sep 17 00:00:00 2001 From: Justin Chen <54879025+justschen@users.noreply.github.com> Date: Tue, 30 Apr 2024 01:25:22 +0800 Subject: [PATCH 089/104] issue reporter wording/ui fixes (#211654) first pass at some debt and ui changes --- .../issue/issueReporterPage.ts | 2 +- .../issue/issueReporterService.ts | 31 +++++++++++++++---- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/src/vs/code/electron-sandbox/issue/issueReporterPage.ts b/src/vs/code/electron-sandbox/issue/issueReporterPage.ts index 01e081224922a..7cf33372a9724 100644 --- a/src/vs/code/electron-sandbox/issue/issueReporterPage.ts +++ b/src/vs/code/electron-sandbox/issue/issueReporterPage.ts @@ -38,7 +38,7 @@ export default (): string => `
- + diff --git a/src/vs/code/electron-sandbox/issue/issueReporterService.ts b/src/vs/code/electron-sandbox/issue/issueReporterService.ts index bfb1d01e17d8d..6edb382d5ac7a 100644 --- a/src/vs/code/electron-sandbox/issue/issueReporterService.ts +++ b/src/vs/code/electron-sandbox/issue/issueReporterService.ts @@ -38,7 +38,8 @@ interface SearchResult { enum IssueSource { VSCode = 'vscode', Extension = 'extension', - Marketplace = 'marketplace' + Marketplace = 'marketplace', + Unknown = 'unknown' } export class IssueReporter extends Disposable { @@ -289,6 +290,13 @@ export class IssueReporter extends Disposable { this.updatePerformanceInfo(info as Partial); }); } + + // Resets placeholder + const descriptionTextArea = this.getElementById('issue-title'); + if (descriptionTextArea) { + descriptionTextArea.placeholder = localize('undefinedPlaceholder', "Please enter a title"); + } + this.updatePreviewButtonState(); this.setSourceOptions(); this.render(); @@ -334,6 +342,17 @@ export class IssueReporter extends Disposable { hide(problemSourceHelpText); } + const descriptionTextArea = this.getElementById('issue-title'); + if (value === IssueSource.VSCode) { + descriptionTextArea.placeholder = localize('vscodePlaceholder', "E.g Workbench is missing problems panel"); + } else if (value === IssueSource.Extension) { + descriptionTextArea.placeholder = localize('extensionPlaceholder', "E.g. Missing alt text on extension readme image"); + } else if (value === IssueSource.Marketplace) { + descriptionTextArea.placeholder = localize('marketplacePlaceholder', "E.g Cannot disable installed extension"); + } else { + descriptionTextArea.placeholder = localize('undefinedPlaceholder', "Please enter a title"); + } + let fileOnExtension, fileOnMarketplace = false; if (value === IssueSource.Extension) { fileOnExtension = true; @@ -712,7 +731,7 @@ export class IssueReporter extends Disposable { reset(typeSelect, makeOption(IssueType.Bug, localize('bugReporter', "Bug Report")), makeOption(IssueType.FeatureRequest, localize('featureRequest', "Feature Request")), - makeOption(IssueType.PerformanceIssue, localize('performanceIssue', "Performance Issue")) + makeOption(IssueType.PerformanceIssue, localize('performanceIssue', "Performance Issue (freeze, slow, crash)")) ); typeSelect.value = issueType.toString(); @@ -747,14 +766,14 @@ export class IssueReporter extends Disposable { sourceSelect.innerText = ''; sourceSelect.append(this.makeOption('', localize('selectSource', "Select source"), true)); - sourceSelect.append(this.makeOption('vscode', localize('vscode', "Visual Studio Code"), false)); - sourceSelect.append(this.makeOption('extension', localize('extension', "An extension"), false)); + sourceSelect.append(this.makeOption(IssueSource.VSCode, localize('vscode', "Visual Studio Code"), false)); + sourceSelect.append(this.makeOption(IssueSource.Extension, localize('extension', "A VS Code extension"), false)); if (this.configuration.product.reportMarketplaceIssueUrl) { - sourceSelect.append(this.makeOption('marketplace', localize('marketplace', "Extensions marketplace"), false)); + sourceSelect.append(this.makeOption(IssueSource.Marketplace, localize('marketplace', "Extensions Marketplace"), false)); } if (issueType !== IssueType.FeatureRequest) { - sourceSelect.append(this.makeOption('unknown', localize('unknown', "Don't know"), false)); + sourceSelect.append(this.makeOption(IssueSource.Unknown, localize('unknown', "Don't know"), false)); } if (selected !== -1 && selected < sourceSelect.options.length) { From 7065120668de2b9bb2ef768c9b42c53c9490c70d Mon Sep 17 00:00:00 2001 From: Michael Lively Date: Mon, 29 Apr 2024 10:59:29 -0700 Subject: [PATCH 090/104] Don't show Run Section button in folded cell hint when no code cells present (#211658) No folded run button when no code cells --- .../browser/view/cellParts/foldedCellHint.ts | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/view/cellParts/foldedCellHint.ts b/src/vs/workbench/contrib/notebook/browser/view/cellParts/foldedCellHint.ts index 25b3967c84628..04d42f4ad1eb4 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/cellParts/foldedCellHint.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/cellParts/foldedCellHint.ts @@ -14,7 +14,7 @@ import { MarkupCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewM import { ICellRange } from 'vs/workbench/contrib/notebook/common/notebookRange'; import { executingStateIcon } from 'vs/workbench/contrib/notebook/browser/notebookIcons'; import { INotebookExecutionStateService } from 'vs/workbench/contrib/notebook/common/notebookExecutionStateService'; -import { NotebookCellExecutionState } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { CellKind, NotebookCellExecutionState } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { MutableDisposable } from 'vs/base/common/lifecycle'; export class FoldedCellHint extends CellContentPart { @@ -49,7 +49,13 @@ export class FoldedCellHint extends CellContentPart { const idx = this._notebookEditor.getViewModel().getCellIndex(element); const length = this._notebookEditor.getViewModel().getFoldedLength(idx); - DOM.reset(this._container, this.getRunFoldedSectionButton({ start: idx, end: idx + length + 1 }), this.getHiddenCellsLabel(length), this.getHiddenCellHintButton(element)); + const runSectionButton = this.getRunFoldedSectionButton({ start: idx, end: idx + length + 1 }); + if (!runSectionButton) { + DOM.reset(this._container, this.getHiddenCellsLabel(length), this.getHiddenCellHintButton(element)); + } else { + DOM.reset(this._container, runSectionButton, this.getHiddenCellsLabel(length), this.getHiddenCellHintButton(element)); + } + DOM.show(this._container); const foldHintTop = element.layoutInfo.previewHeight; @@ -83,10 +89,16 @@ export class FoldedCellHint extends CellContentPart { return expandIcon; } - private getRunFoldedSectionButton(range: ICellRange): HTMLElement { + private getRunFoldedSectionButton(range: ICellRange): HTMLElement | undefined { const runAllContainer = DOM.$('span.folded-cell-run-section-button'); const cells = this._notebookEditor.getCellsInRange(range); + // Check if any cells are code cells, if not, we won't show the run button + const hasCodeCells = cells.some(cell => cell.cellKind === CellKind.Code); + if (!hasCodeCells) { + return undefined; + } + const isRunning = cells.some(cell => { const cellExecution = this._notebookExecutionStateService.getCellExecution(cell.uri); return cellExecution && cellExecution.state === NotebookCellExecutionState.Executing; From dd1225cd0dd09208acebb818ddd659665be49cc1 Mon Sep 17 00:00:00 2001 From: Michael Lively Date: Mon, 29 Apr 2024 11:05:40 -0700 Subject: [PATCH 091/104] Fix misplaced semicolons (#211661) fix misplaced semicolons? --- .../notebook/browser/viewModel/notebookOutlineProvider.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/notebookOutlineProvider.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/notebookOutlineProvider.ts index 999113306e6c9..fe834260b9396 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/notebookOutlineProvider.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/notebookOutlineProvider.ts @@ -50,7 +50,7 @@ export class NotebookCellOutlineProvider { } private readonly _outlineEntryFactory: NotebookOutlineEntryFactory; - private readonly delayedOutlineRecompute: Delayer;; + private readonly delayedOutlineRecompute: Delayer; constructor( private readonly _editor: INotebookEditor, private readonly _target: OutlineTarget, @@ -65,7 +65,7 @@ export class NotebookCellOutlineProvider { const delayerRecomputeActive = this._disposables.add(new Delayer(200)); this._disposables.add(_editor.onDidChangeSelection(() => { delayerRecomputeActive.trigger(() => this._recomputeActive()); - }, this)) + }, this)); // .3s of a delay is sufficient, 100-200s is too quick and will unnecessarily block the ui thread. // Given we're only updating the outline when the user types, we can afford to wait a bit. @@ -115,10 +115,10 @@ export class NotebookCellOutlineProvider { if (!this._entries.length) { this._recomputeState(); } - } + }; this._disposables.add(this._editor.onDidChangeModel(monitorModelChanges)); monitorModelChanges(); - this._recomputeState() + this._recomputeState(); } dispose(): void { From 4c32ab9d953c0d622442e79c9a53f0f75d69b8bf Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 29 Apr 2024 11:21:31 -0700 Subject: [PATCH 092/104] Show errors on paste/drop edit resolve/apply error (#211663) Fixes #211137 --- .../dropOrPasteInto/browser/postEditWidget.ts | 46 +++++++++++++++---- 1 file changed, 36 insertions(+), 10 deletions(-) diff --git a/src/vs/editor/contrib/dropOrPasteInto/browser/postEditWidget.ts b/src/vs/editor/contrib/dropOrPasteInto/browser/postEditWidget.ts index 7415060262ab3..9443f52cc0525 100644 --- a/src/vs/editor/contrib/dropOrPasteInto/browser/postEditWidget.ts +++ b/src/vs/editor/contrib/dropOrPasteInto/browser/postEditWidget.ts @@ -7,6 +7,8 @@ import * as dom from 'vs/base/browser/dom'; import { Button } from 'vs/base/browser/ui/button/button'; import { toAction } from 'vs/base/common/actions'; import { CancellationToken } from 'vs/base/common/cancellation'; +import { toErrorMessage } from 'vs/base/common/errorMessage'; +import { isCancellationError } from 'vs/base/common/errors'; import { Event } from 'vs/base/common/event'; import { Disposable, MutableDisposable, toDisposable } from 'vs/base/common/lifecycle'; import 'vs/css!./postEditWidget'; @@ -16,10 +18,12 @@ import { Range } from 'vs/editor/common/core/range'; import { DocumentDropEdit, DocumentPasteEdit } from 'vs/editor/common/languages'; import { TrackedRangeStickiness } from 'vs/editor/common/model'; import { createCombinedWorkspaceEdit } from 'vs/editor/contrib/dropOrPasteInto/browser/edit'; +import { localize } from 'vs/nls'; import { IContextKey, IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; +import { INotificationService } from 'vs/platform/notification/common/notification'; interface EditSet { @@ -143,6 +147,7 @@ export class PostEditWidgetManager { + const model = this._editor.getModel(); + if (!model) { + return; + } + + await model.undo(); + this.applyEditAndShowIfNeeded(ranges, { activeEditIndex: newEditIndex, allEdits: edits.allEdits }, canShowWidget, resolve, token); + }; + + const handleError = (e: Error, message: string) => { + if (isCancellationError(e)) { + return; + } + + this._notificationService.error(message); + if (canShowWidget) { + this.show(ranges[0], edits, onDidSelectEdit); + } + }; + + let resolvedEdit: T; + try { + resolvedEdit = await resolve(edit, token); + } catch (e) { + return handleError(e, localize('resolveError', "Error resolving edit '{0}':\n{1}", edit.title, toErrorMessage(e))); + } + if (token.isCancellationRequested) { return; } @@ -183,6 +215,8 @@ export class PostEditWidgetManager 1) { - this.show(editRange ?? primaryRange, edits, async (newEditIndex) => { - const model = this._editor.getModel(); - if (!model) { - return; - } - - await model.undo(); - this.applyEditAndShowIfNeeded(ranges, { activeEditIndex: newEditIndex, allEdits: edits.allEdits }, canShowWidget, resolve, token); - }); + this.show(editRange ?? primaryRange, edits, onDidSelectEdit); } } From c67ccc70ece5f472ec25464d3eeb874cfccee9f1 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Mon, 29 Apr 2024 12:15:11 -0700 Subject: [PATCH 093/104] Add sampleRequest to static participant registration (#211664) * Add sampleRequest to static participant registration Bringing microsoft/vscode-copilot-release#1165 to main * Update src/vs/workbench/contrib/chat/browser/chatParticipantContributions.ts Co-authored-by: Raymond Zhao <7199958+rzhao271@users.noreply.github.com> --------- Co-authored-by: Raymond Zhao <7199958+rzhao271@users.noreply.github.com> --- src/vs/workbench/contrib/chat/browser/chat.contribution.ts | 2 +- .../contrib/chat/browser/chatParticipantContributions.ts | 7 ++++++- .../contrib/chat/common/chatParticipantContribTypes.ts | 1 + 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/chat/browser/chat.contribution.ts b/src/vs/workbench/contrib/chat/browser/chat.contribution.ts index 20c87e73203ce..e6d70783da26d 100644 --- a/src/vs/workbench/contrib/chat/browser/chat.contribution.ts +++ b/src/vs/workbench/contrib/chat/browser/chat.contribution.ts @@ -269,7 +269,7 @@ class ChatSlashStaticSlashCommandsContribution extends Disposable { .filter(a => a.locations.includes(ChatAgentLocation.Panel)) .map(async a => { const agentWithLeader = `${chatAgentLeader}${a.name}`; - const actionArg: IChatExecuteActionContext = { inputValue: `${agentWithLeader} ${a.metadata.sampleRequest}` }; + const actionArg: IChatExecuteActionContext = { inputValue: `${agentWithLeader} ${a.metadata.sampleRequest ?? ''}` }; const urlSafeArg = encodeURIComponent(JSON.stringify(actionArg)); const description = a.description ? `- ${a.description}` : ''; const agentLine = `* [\`${agentWithLeader}\`](command:${SubmitAction.ID}?${urlSafeArg}) ${description}`; diff --git a/src/vs/workbench/contrib/chat/browser/chatParticipantContributions.ts b/src/vs/workbench/contrib/chat/browser/chatParticipantContributions.ts index e419f12a0ff26..3ba58f37bf98a 100644 --- a/src/vs/workbench/contrib/chat/browser/chatParticipantContributions.ts +++ b/src/vs/workbench/contrib/chat/browser/chatParticipantContributions.ts @@ -54,6 +54,10 @@ const chatParticipantExtensionPoint = extensionsRegistry.ExtensionsRegistry.regi description: localize('chatCommandSticky', "Whether invoking the command puts the chat into a persistent mode, where the command is automatically added to the chat input for the next message."), type: 'boolean' }, + sampleRequest: { + description: localize('chatSampleRequest', "When the user clicks this participant in `/help`, this text will be submitted to the participant."), + type: 'string' + }, defaultImplicitVariables: { markdownDescription: '**Only** allowed for extensions that have the `chatParticipantAdditions` proposal. The names of the variables that are invoked by default', type: 'array', @@ -83,7 +87,7 @@ const chatParticipantExtensionPoint = extensionsRegistry.ExtensionsRegistry.regi type: 'string' }, sampleRequest: { - description: localize('chatCommandSampleRequest', "When the user clicks this command in `/help`, this text will be submitted to this participant."), + description: localize('chatCommandSampleRequest', "When the user clicks this command in `/help`, this text will be submitted to the participant."), type: 'string' }, isSticky: { @@ -209,6 +213,7 @@ export class ChatExtensionPointHandler implements IWorkbenchContribution { description: providerDescriptor.description, metadata: { isSticky: providerDescriptor.isSticky, + sampleRequest: providerDescriptor.sampleRequest, }, name: providerDescriptor.name, isDefault: providerDescriptor.isDefault, diff --git a/src/vs/workbench/contrib/chat/common/chatParticipantContribTypes.ts b/src/vs/workbench/contrib/chat/common/chatParticipantContribTypes.ts index 3a190bf172b4d..4c4449bbaf92b 100644 --- a/src/vs/workbench/contrib/chat/common/chatParticipantContribTypes.ts +++ b/src/vs/workbench/contrib/chat/common/chatParticipantContribTypes.ts @@ -20,6 +20,7 @@ export interface IRawChatParticipantContribution { description?: string; isDefault?: boolean; isSticky?: boolean; + sampleRequest?: string; commands?: IRawChatCommandContribution[]; defaultImplicitVariables?: string[]; locations?: RawChatParticipantLocation[]; From 6dffc4040c043f0d50bbc388bfe50da3beb39e4c Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Mon, 29 Apr 2024 15:34:12 -0700 Subject: [PATCH 094/104] fix: run tests in explorer context menu not working (#211670) Fixes #211338 --- src/vs/workbench/contrib/testing/common/testService.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/testing/common/testService.ts b/src/vs/workbench/contrib/testing/common/testService.ts index e26b2f2bd80e3..7af1ee2c33128 100644 --- a/src/vs/workbench/contrib/testing/common/testService.ts +++ b/src/vs/workbench/contrib/testing/common/testService.ts @@ -198,6 +198,8 @@ export const testsUnderUri = async function* (testService: ITestService, ident: } else if (!test.item.uri) { queue.push(test.children.values()); continue; + } else if (ident.extUri.isEqualOrParent(test.item.uri, uri)) { + yield test; } else if (ident.extUri.isEqualOrParent(uri, test.item.uri)) { if (test.expand === TestItemExpandState.Expandable) { await testService.collection.expand(test.item.extId, 1); @@ -206,8 +208,6 @@ export const testsUnderUri = async function* (testService: ITestService, ident: await waitForTestToBeIdle(testService, test); } queue.push(test.children.values()); - } else if (ident.extUri.isEqualOrParent(test.item.uri, uri)) { - yield test; } } } From 10bea6aa291aea6da506fc577f7c1ea2fb0ed930 Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Mon, 29 Apr 2024 15:54:41 -0700 Subject: [PATCH 095/104] debug: fix ctrl+c overwriting prompt text in debug terminal (#211673) Fixes #209341 --- src/vs/workbench/api/node/extHostDebugService.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/api/node/extHostDebugService.ts b/src/vs/workbench/api/node/extHostDebugService.ts index 5e50ef5c47e7e..fd03fd9ea327d 100644 --- a/src/vs/workbench/api/node/extHostDebugService.ts +++ b/src/vs/workbench/api/node/extHostDebugService.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { createCancelablePromise, firstParallel } from 'vs/base/common/async'; +import { createCancelablePromise, firstParallel, timeout } from 'vs/base/common/async'; import { IDisposable } from 'vs/base/common/lifecycle'; import * as platform from 'vs/base/common/platform'; import * as nls from 'vs/nls'; @@ -127,6 +127,7 @@ export class ExtHostDebugService extends ExtHostDebugServiceBase { } else { if (terminal.state.isInteractedWith) { terminal.sendText('\u0003'); // Ctrl+C for #106743. Not part of the same command for #107969 + await timeout(200); // mirroring /~https://github.com/microsoft/vscode/blob/c67ccc70ece5f472ec25464d3eeb874cfccee9f1/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts#L852-L857 } if (configProvider.getConfiguration('debug.terminal').get('clearBeforeReusing')) { From 830b537658bceff8ac3cc72de0ea146e18f5a7de Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Tue, 30 Apr 2024 09:07:54 +1000 Subject: [PATCH 096/104] Track markdown rendering delays in parameter hints (#211591) * Track markdown rendering delays in parameter hints * Address code review comments --- .../browser/parameterHintsWidget.ts | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/vs/editor/contrib/parameterHints/browser/parameterHintsWidget.ts b/src/vs/editor/contrib/parameterHints/browser/parameterHintsWidget.ts index 46d92a532e948..f5b8af528e3d5 100644 --- a/src/vs/editor/contrib/parameterHints/browser/parameterHintsWidget.ts +++ b/src/vs/editor/contrib/parameterHints/browser/parameterHintsWidget.ts @@ -26,6 +26,8 @@ import { IOpenerService } from 'vs/platform/opener/common/opener'; import { listHighlightForeground, registerColor } from 'vs/platform/theme/common/colorRegistry'; import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; import { ThemeIcon } from 'vs/base/common/themables'; +import { StopWatch } from 'vs/base/common/stopwatch'; +import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; const $ = dom.$; @@ -61,6 +63,7 @@ export class ParameterHintsWidget extends Disposable implements IContentWidget { @IContextKeyService contextKeyService: IContextKeyService, @IOpenerService openerService: IOpenerService, @ILanguageService languageService: ILanguageService, + @ITelemetryService private readonly telemetryService: ITelemetryService, ) { super(); @@ -272,12 +275,30 @@ export class ParameterHintsWidget extends Disposable implements IContentWidget { } private renderMarkdownDocs(markdown: IMarkdownString | undefined): IMarkdownRenderResult { + const stopWatch = new StopWatch(); const renderedContents = this.renderDisposeables.add(this.markdownRenderer.render(markdown, { asyncRenderCallback: () => { this.domNodes?.scrollbar.scanDomNode(); } })); renderedContents.element.classList.add('markdown-docs'); + + type RenderMarkdownPerformanceClassification = { + owner: 'donjayamanne'; + comment: 'Measure the time taken to render markdown for parameter hints'; + renderDuration: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'Time in ms to render the markdown' }; + }; + + type RenderMarkdownPerformanceEvent = { + renderDuration: number; + }; + const renderDuration = stopWatch.elapsed(); + if (renderDuration > 300) { + this.telemetryService.publicLog2('parameterHints.parseMarkdown', { + renderDuration + }); + } + return renderedContents; } From 1060a5622396a5e82e8007a9cac254affdd9fe99 Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Mon, 29 Apr 2024 16:19:45 -0700 Subject: [PATCH 097/104] views: fix view filter jumping on resize/view open (#211676) Fixes #211180 --- src/vs/workbench/browser/parts/views/viewFilter.ts | 8 ++++++++ src/vs/workbench/browser/parts/views/viewPane.ts | 4 +++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/browser/parts/views/viewFilter.ts b/src/vs/workbench/browser/parts/views/viewFilter.ts index b6285e45c7199..3331c892d0c29 100644 --- a/src/vs/workbench/browser/parts/views/viewFilter.ts +++ b/src/vs/workbench/browser/parts/views/viewFilter.ts @@ -81,6 +81,7 @@ export class FilterWidget extends Widget { private moreFiltersActionViewItem: MoreFiltersActionViewItem | undefined; private isMoreFiltersChecked: boolean = false; + private lastWidth?: number; private focusTracker: DOM.IFocusTracker; public get onDidFocus() { return this.focusTracker.onDidFocus; } @@ -147,6 +148,13 @@ export class FilterWidget extends Widget { this.element.parentElement?.classList.toggle('grow', width > 700); this.element.classList.toggle('small', width < 400); this.adjustInputBox(); + this.lastWidth = width; + } + + relayout() { + if (this.lastWidth) { + this.layout(this.lastWidth); + } } checkMoreFilters(checked: boolean): void { diff --git a/src/vs/workbench/browser/parts/views/viewPane.ts b/src/vs/workbench/browser/parts/views/viewPane.ts index 6eae565005161..c62f1b0ab4745 100644 --- a/src/vs/workbench/browser/parts/views/viewPane.ts +++ b/src/vs/workbench/browser/parts/views/viewPane.ts @@ -688,7 +688,9 @@ export abstract class ViewPane extends Pane implements IView { override get trapsArrowNavigation(): boolean { return true; } override render(container: HTMLElement): void { container.classList.add('viewpane-filter-container'); - append(container, that.getFilterWidget()!.element); + const filter = that.getFilterWidget()!; + append(container, filter.element); + filter.relayout(); } }; } From f95b8475ab11d6fe7c73159d09071024bb8d16d7 Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Mon, 29 Apr 2024 16:23:44 -0700 Subject: [PATCH 098/104] debug: gracefully shut down debug sessions during eh restart (#211677) Fixes #210236 --- src/vs/workbench/contrib/debug/browser/debugService.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/debug/browser/debugService.ts b/src/vs/workbench/contrib/debug/browser/debugService.ts index d7e5dc80a3cf5..c5db527c52649 100644 --- a/src/vs/workbench/contrib/debug/browser/debugService.ts +++ b/src/vs/workbench/contrib/debug/browser/debugService.ts @@ -111,7 +111,7 @@ export class DebugService implements IDebugService { @ICommandService private readonly commandService: ICommandService, @IQuickInputService private readonly quickInputService: IQuickInputService, @IWorkspaceTrustRequestService private readonly workspaceTrustRequestService: IWorkspaceTrustRequestService, - @IUriIdentityService private readonly uriIdentityService: IUriIdentityService + @IUriIdentityService private readonly uriIdentityService: IUriIdentityService, ) { this.breakpointsToSendOnResourceSaved = new Set(); @@ -200,6 +200,13 @@ export class DebugService implements IDebugService { } })); + this.disposables.add(extensionService.onWillStop(evt => { + evt.veto( + this.stopSession(undefined).then(() => false), + nls.localize('stoppingDebug', 'Stopping debug sessions...'), + ); + })); + this.initContextKeys(contextKeyService); } From bc278dfe7c8b0b050ae57f88bfdc4073dff30364 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 29 Apr 2024 17:54:50 -0700 Subject: [PATCH 099/104] Fix workspace symbol search (#211681) For #211672 --- .../src/languageFeatures/workspaceSymbols.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/typescript-language-features/src/languageFeatures/workspaceSymbols.ts b/extensions/typescript-language-features/src/languageFeatures/workspaceSymbols.ts index 43e4c3a5f384e..98995cc6baa17 100644 --- a/extensions/typescript-language-features/src/languageFeatures/workspaceSymbols.ts +++ b/extensions/typescript-language-features/src/languageFeatures/workspaceSymbols.ts @@ -89,7 +89,7 @@ class TypeScriptWorkspaceSymbolProvider implements vscode.WorkspaceSymbolProvide } private toSymbolInformation(item: Proto.NavtoItem): vscode.SymbolInformation | undefined { - if (!item.containerName || item.kind === 'alias') { + if (item.kind === 'alias' && !item.containerName) { return; } From 0d9da1e50e7cda1c699fa74b60f9a81799383e20 Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Tue, 30 Apr 2024 16:28:40 +1000 Subject: [PATCH 100/104] Delete pending notebook executions on interrupt (#211687) --- src/vs/workbench/api/common/extHostNotebookKernels.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vs/workbench/api/common/extHostNotebookKernels.ts b/src/vs/workbench/api/common/extHostNotebookKernels.ts index 49dcbf40085f6..ecb6b4a7db3ce 100644 --- a/src/vs/workbench/api/common/extHostNotebookKernels.ts +++ b/src/vs/workbench/api/common/extHostNotebookKernels.ts @@ -433,6 +433,7 @@ export class ExtHostNotebookKernels implements ExtHostNotebookKernelsShape { if (obj.controller.interruptHandler) { // If we're interrupting all cells, we also need to cancel the notebook level execution. const items = this._activeNotebookExecutions.get(document.uri); + this._activeNotebookExecutions.delete(document.uri); if (handles.length && Array.isArray(items) && items.length) { items.forEach(d => d.dispose()); } From 4a37deeebaff9e2dec887373bde9caa2f781722c Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Tue, 30 Apr 2024 15:23:13 +0200 Subject: [PATCH 101/104] Allow extensions to set hybrid port source (#211696) Part of #211647 --- src/vs/workbench/api/browser/mainThreadTunnelService.ts | 7 ++++++- src/vs/workbench/api/common/extHost.protocol.ts | 3 ++- src/vscode-dts/vscode.proposed.resolvers.d.ts | 3 ++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/api/browser/mainThreadTunnelService.ts b/src/vs/workbench/api/browser/mainThreadTunnelService.ts index 4fb13ab62311a..5b8cf2637fcdf 100644 --- a/src/vs/workbench/api/browser/mainThreadTunnelService.ts +++ b/src/vs/workbench/api/browser/mainThreadTunnelService.ts @@ -7,7 +7,7 @@ import * as nls from 'vs/nls'; import { MainThreadTunnelServiceShape, MainContext, ExtHostContext, ExtHostTunnelServiceShape, CandidatePortSource, PortAttributesSelector, TunnelDto } from 'vs/workbench/api/common/extHost.protocol'; import { TunnelDtoConverter } from 'vs/workbench/api/common/extHostTunnelService'; import { extHostNamedCustomer, IExtHostContext } from 'vs/workbench/services/extensions/common/extHostCustomers'; -import { IRemoteExplorerService, PORT_AUTO_FORWARD_SETTING, PORT_AUTO_SOURCE_SETTING, PORT_AUTO_SOURCE_SETTING_OUTPUT } from 'vs/workbench/services/remote/common/remoteExplorerService'; +import { IRemoteExplorerService, PORT_AUTO_FORWARD_SETTING, PORT_AUTO_SOURCE_SETTING, PORT_AUTO_SOURCE_SETTING_HYBRID, PORT_AUTO_SOURCE_SETTING_OUTPUT } from 'vs/workbench/services/remote/common/remoteExplorerService'; import { ITunnelProvider, ITunnelService, TunnelCreationOptions, TunnelProviderFeatures, TunnelOptions, RemoteTunnel, ProvidedPortAttributes, PortAttributesProvider, TunnelProtocol } from 'vs/platform/tunnel/common/tunnel'; import { Disposable } from 'vs/base/common/lifecycle'; import type { TunnelDescription } from 'vs/platform/remote/common/remoteAuthorityResolver'; @@ -223,6 +223,11 @@ export class MainThreadTunnelService extends Disposable implements MainThreadTun .registerDefaultConfigurations([{ overrides: { 'remote.autoForwardPortsSource': PORT_AUTO_SOURCE_SETTING_OUTPUT } }]); break; } + case CandidatePortSource.Hybrid: { + Registry.as(ConfigurationExtensions.Configuration) + .registerDefaultConfigurations([{ overrides: { 'remote.autoForwardPortsSource': PORT_AUTO_SOURCE_SETTING_HYBRID } }]); + break; + } default: // Do nothing, the defaults for these settings should be used. } }).catch(() => { diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index 16e6fb46787ea..ed133c366b22d 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -1598,7 +1598,8 @@ export interface MainThreadWindowShape extends IDisposable { export enum CandidatePortSource { None = 0, Process = 1, - Output = 2 + Output = 2, + Hybrid = 3 } export interface PortAttributesSelector { diff --git a/src/vscode-dts/vscode.proposed.resolvers.d.ts b/src/vscode-dts/vscode.proposed.resolvers.d.ts index 3bf1f93eb7de3..4f49cdf7d4af8 100644 --- a/src/vscode-dts/vscode.proposed.resolvers.d.ts +++ b/src/vscode-dts/vscode.proposed.resolvers.d.ts @@ -141,7 +141,8 @@ declare module 'vscode' { export enum CandidatePortSource { None = 0, Process = 1, - Output = 2 + Output = 2, + Hybrid = 3 } export type ResolverResult = (ResolvedAuthority | ManagedResolvedAuthority) & ResolvedOptions & TunnelInformation; From 431afbe45908fc8754746e6e9c958fde85ceac4d Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 30 Apr 2024 11:27:07 -0700 Subject: [PATCH 102/104] Log trigger reason in TS refactor telemetry (#211652) --- .../src/languageFeatures/refactor.ts | 32 ++++++++++++------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/extensions/typescript-language-features/src/languageFeatures/refactor.ts b/extensions/typescript-language-features/src/languageFeatures/refactor.ts index 075fee940180d..8dc062357533e 100644 --- a/extensions/typescript-language-features/src/languageFeatures/refactor.ts +++ b/extensions/typescript-language-features/src/languageFeatures/refactor.ts @@ -40,6 +40,7 @@ function toWorkspaceEdit(client: ITypeScriptServiceClient, edits: readonly Proto namespace DidApplyRefactoringCommand { export interface Args { readonly action: string; + readonly trigger: vscode.CodeActionTriggerKind; } } @@ -56,6 +57,7 @@ class DidApplyRefactoringCommand implements Command { "refactor.execute" : { "owner": "mjbvz", "action" : { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" }, + "trigger" : { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" }, "${include}": [ "${TypeScriptCommonProperties}" ] @@ -63,6 +65,7 @@ class DidApplyRefactoringCommand implements Command { */ this.telemetryReporter.logTelemetry('refactor.execute', { action: args.action, + trigger: args.trigger, }); } } @@ -71,6 +74,7 @@ namespace SelectRefactorCommand { readonly document: vscode.TextDocument; readonly refactor: Proto.ApplicableRefactorInfo; readonly rangeOrSelection: vscode.Range | vscode.Selection; + readonly trigger: vscode.CodeActionTriggerKind; } } @@ -97,7 +101,7 @@ class SelectRefactorCommand implements Command { return; } - const tsAction = new InlinedCodeAction(this.client, args.document, args.refactor, selected.action, args.rangeOrSelection); + const tsAction = new InlinedCodeAction(this.client, args.document, args.refactor, selected.action, args.rangeOrSelection, args.trigger); await tsAction.resolve(nulToken); if (tsAction.edit) { @@ -118,6 +122,7 @@ namespace MoveToFileRefactorCommand { readonly document: vscode.TextDocument; readonly action: Proto.RefactorActionInfo; readonly range: vscode.Range; + readonly trigger: vscode.CodeActionTriggerKind; } } @@ -158,7 +163,7 @@ class MoveToFileRefactorCommand implements Command { return; } - await this.didApplyCommand.execute({ action: args.action.name }); + await this.didApplyCommand.execute({ action: args.action.name, trigger: args.trigger }); } private async getTargetFile(document: vscode.TextDocument, file: string, range: vscode.Range): Promise { @@ -347,6 +352,7 @@ class InlinedCodeAction extends vscode.CodeAction { public readonly refactor: Proto.ApplicableRefactorInfo, public readonly action: Proto.RefactorActionInfo, public readonly range: vscode.Range, + trigger: vscode.CodeActionTriggerKind, ) { const title = action.description; super(title, InlinedCodeAction.getKind(action)); @@ -358,7 +364,7 @@ class InlinedCodeAction extends vscode.CodeAction { this.command = { title, command: DidApplyRefactoringCommand.ID, - arguments: [{ action: action.name }], + arguments: [{ action: action.name, trigger } satisfies DidApplyRefactoringCommand.Args], }; } @@ -420,6 +426,7 @@ class MoveToFileCodeAction extends vscode.CodeAction { document: vscode.TextDocument, action: Proto.RefactorActionInfo, range: vscode.Range, + trigger: vscode.CodeActionTriggerKind, ) { super(action.description, Move_File.kind); @@ -430,7 +437,7 @@ class MoveToFileCodeAction extends vscode.CodeAction { this.command = { title: action.description, command: MoveToFileRefactorCommand.ID, - arguments: [{ action, document, range }] + arguments: [{ action, document, range, trigger } satisfies MoveToFileRefactorCommand.Args] }; } } @@ -439,13 +446,14 @@ class SelectCodeAction extends vscode.CodeAction { constructor( info: Proto.ApplicableRefactorInfo, document: vscode.TextDocument, - rangeOrSelection: vscode.Range | vscode.Selection + rangeOrSelection: vscode.Range | vscode.Selection, + trigger: vscode.CodeActionTriggerKind, ) { super(info.description, vscode.CodeActionKind.Refactor); this.command = { title: info.description, command: SelectRefactorCommand.ID, - arguments: [{ action: this, document, refactor: info, rangeOrSelection }] + arguments: [{ document, refactor: info, rangeOrSelection, trigger } satisfies SelectRefactorCommand.Args] }; } } @@ -552,7 +560,7 @@ class TypeScriptRefactorProvider implements vscode.CodeActionProvider { if (this.client.apiVersion.lt(API.v430)) { // Don't show 'infer return type' refactoring unless it has been explicitly requested @@ -603,15 +611,16 @@ class TypeScriptRefactorProvider implements vscode.CodeActionProvider { for (const refactor of refactors) { if (refactor.inlineable === false) { - yield new SelectCodeAction(refactor, document, rangeOrSelection); + yield new SelectCodeAction(refactor, document, rangeOrSelection, context.triggerKind); } else { for (const action of refactor.actions) { - for (const codeAction of this.refactorActionToCodeActions(document, refactor, action, rangeOrSelection, refactor.actions)) { + for (const codeAction of this.refactorActionToCodeActions(document, context, refactor, action, rangeOrSelection, refactor.actions)) { yield codeAction; } } @@ -621,6 +630,7 @@ class TypeScriptRefactorProvider implements vscode.CodeActionProvider Date: Tue, 30 Apr 2024 11:27:22 -0700 Subject: [PATCH 103/104] Add eslint rule for disallowing dangerous type assertions (#211669) This adds a new (off by default) eslint rule that disables two specific types of dangerous type assertions: ```ts {...}; {...} as Type; ``` These are bad because they can easily hide missing properties and strictness errors Right now just adding this rule but will assign out fixes to owners in different areas of the code --- .../code-no-dangerous-type-assertions.ts | 40 +++++++++++++++++++ .eslintrc.json | 1 + .../contrib/folding/browser/foldingRanges.ts | 2 +- .../browser/actions/chatCodeblockActions.ts | 2 +- .../markers/browser/markersViewActions.ts | 6 +-- 5 files changed, 46 insertions(+), 5 deletions(-) create mode 100644 .eslintplugin/code-no-dangerous-type-assertions.ts diff --git a/.eslintplugin/code-no-dangerous-type-assertions.ts b/.eslintplugin/code-no-dangerous-type-assertions.ts new file mode 100644 index 0000000000000..5cf12b858f610 --- /dev/null +++ b/.eslintplugin/code-no-dangerous-type-assertions.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 * as eslint from 'eslint'; +import { TSESTree } from '@typescript-eslint/experimental-utils'; + +export = new class NoDangerousTypeAssertions implements eslint.Rule.RuleModule { + + create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener { + // Disable in tests for now + if (context.getFilename().includes('.test')) { + return {}; + } + + return { + // Disallow type assertions on object literals: { ... } or {} as T + ['TSTypeAssertion > ObjectExpression, TSAsExpression > ObjectExpression']: (node: any) => { + const objectNode = node as TSESTree.Node; + + const parent = objectNode.parent as TSESTree.TSTypeAssertion | TSESTree.TSAsExpression; + if ( + // Allow `as const` assertions + (parent.typeAnnotation.type === 'TSTypeReference' && parent.typeAnnotation.typeName.type === 'Identifier' && parent.typeAnnotation.typeName.name === 'cost') + + // For also now still allow `any` casts + || (parent.typeAnnotation.type === 'TSAnyKeyword') + ) { + return; + } + + context.report({ + node, + message: "Don't use type assertions for creating objects as this can hide type errors." + }); + }, + }; + } +}; diff --git a/.eslintrc.json b/.eslintrc.json index 83e5bf34dae04..8382822ac14af 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -73,6 +73,7 @@ "local/code-parameter-properties-must-have-explicit-accessibility": "warn", "local/code-no-nls-in-standalone-editor": "warn", "local/code-no-potentially-unsafe-disposables": "warn", + "local/code-no-dangerous-type-assertions": "off", "local/code-no-standalone-editor": "warn", "local/code-no-unexternalized-strings": "warn", "local/code-must-use-super-dispose": "warn", diff --git a/src/vs/editor/contrib/folding/browser/foldingRanges.ts b/src/vs/editor/contrib/folding/browser/foldingRanges.ts index 5c800345b4826..ee23abbfc7479 100644 --- a/src/vs/editor/contrib/folding/browser/foldingRanges.ts +++ b/src/vs/editor/contrib/folding/browser/foldingRanges.ts @@ -246,7 +246,7 @@ export class FoldingRegions { } public toFoldRange(index: number): FoldRange { - return { + return { startLineNumber: this._startIndexes[index] & MAX_LINE_NUMBER, endLineNumber: this._endIndexes[index] & MAX_LINE_NUMBER, type: this._types ? this._types[index] : undefined, diff --git a/src/vs/workbench/contrib/chat/browser/actions/chatCodeblockActions.ts b/src/vs/workbench/contrib/chat/browser/actions/chatCodeblockActions.ts index 8bb76ed3bd1ea..455d4f15b1744 100644 --- a/src/vs/workbench/contrib/chat/browser/actions/chatCodeblockActions.ts +++ b/src/vs/workbench/contrib/chat/browser/actions/chatCodeblockActions.ts @@ -370,7 +370,7 @@ export function registerChatCodeBlockActions() { const editorService = accessor.get(IEditorService); const chatService = accessor.get(IChatService); - editorService.openEditor({ contents: context.code, languageId: context.languageId, resource: undefined }); + editorService.openEditor({ contents: context.code, languageId: context.languageId, resource: undefined } satisfies IUntitledTextResourceEditorInput); if (isResponseVM(context.element)) { chatService.notifyUserAction({ diff --git a/src/vs/workbench/contrib/markers/browser/markersViewActions.ts b/src/vs/workbench/contrib/markers/browser/markersViewActions.ts index 74fa00a81ae6a..169dc418962fa 100644 --- a/src/vs/workbench/contrib/markers/browser/markersViewActions.ts +++ b/src/vs/workbench/contrib/markers/browser/markersViewActions.ts @@ -59,7 +59,7 @@ export class MarkersFilters extends Disposable { set excludedFiles(filesExclude: boolean) { if (this._excludedFiles.get() !== filesExclude) { this._excludedFiles.set(filesExclude); - this._onDidChange.fire({ excludedFiles: true }); + this._onDidChange.fire({ excludedFiles: true }); } } @@ -70,7 +70,7 @@ export class MarkersFilters extends Disposable { set activeFile(activeFile: boolean) { if (this._activeFile.get() !== activeFile) { this._activeFile.set(activeFile); - this._onDidChange.fire({ activeFile: true }); + this._onDidChange.fire({ activeFile: true }); } } @@ -81,7 +81,7 @@ export class MarkersFilters extends Disposable { set showWarnings(showWarnings: boolean) { if (this._showWarnings.get() !== showWarnings) { this._showWarnings.set(showWarnings); - this._onDidChange.fire({ showWarnings: true }); + this._onDidChange.fire({ showWarnings: true }); } } From 0f91377252b01d5a62d5989368e745a99e263a39 Mon Sep 17 00:00:00 2001 From: Michael Lively Date: Tue, 30 Apr 2024 12:37:13 -0700 Subject: [PATCH 104/104] Fix nb outline recompute + nb stickyscroll OutlineTarget (#211740) add event firing back + change nb ss outlineTarget --- .../browser/viewModel/notebookOutlineEntryFactory.ts | 2 +- .../notebook/browser/viewModel/notebookOutlineProvider.ts | 5 ++++- .../browser/viewModel/notebookOutlineProviderFactory.ts | 2 +- .../notebook/browser/viewParts/notebookEditorStickyScroll.ts | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/notebookOutlineEntryFactory.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/notebookOutlineEntryFactory.ts index ded82f216173b..00157aaa86ce5 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/notebookOutlineEntryFactory.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/notebookOutlineEntryFactory.ts @@ -45,7 +45,7 @@ function getMarkdownHeadersInCellFallbackToHtmlTags(fullContent: string) { export class NotebookOutlineEntryFactory { private cellOutlineEntryCache: Record = {}; - private readonly cachedMarkdownOutlineEntries = new WeakMap(); + private readonly cachedMarkdownOutlineEntries = new WeakMap(); constructor( private readonly executionStateService: INotebookExecutionStateService ) { } diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/notebookOutlineProvider.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/notebookOutlineProvider.ts index fe834260b9396..1ac843597abab 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/notebookOutlineProvider.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/notebookOutlineProvider.ts @@ -260,7 +260,10 @@ export class NotebookCellOutlineProvider { } })); - this._recomputeActive(); + const { changeEventTriggered } = this._recomputeActive(); + if (!changeEventTriggered) { + this._onDidChange.fire({}); + } } private _recomputeActive(): { changeEventTriggered: boolean } { diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/notebookOutlineProviderFactory.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/notebookOutlineProviderFactory.ts index d5908204c940b..54411bcd29679 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/notebookOutlineProviderFactory.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/notebookOutlineProviderFactory.ts @@ -24,7 +24,7 @@ class NotebookCellOutlineProviderReferenceCollection extends ReferenceCollection export const INotebookCellOutlineProviderFactory = createDecorator('INotebookCellOutlineProviderFactory'); export interface INotebookCellOutlineProviderFactory { - getOrCreate(editor: INotebookEditor, target: OutlineTarget): IReference + getOrCreate(editor: INotebookEditor, target: OutlineTarget): IReference; } export class NotebookCellOutlineProviderFactory implements INotebookCellOutlineProviderFactory { diff --git a/src/vs/workbench/contrib/notebook/browser/viewParts/notebookEditorStickyScroll.ts b/src/vs/workbench/contrib/notebook/browser/viewParts/notebookEditorStickyScroll.ts index 521b8d908f735..52e6889c4bc76 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewParts/notebookEditorStickyScroll.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewParts/notebookEditorStickyScroll.ts @@ -202,7 +202,7 @@ export class NotebookStickyScroll extends Disposable { } private init() { - const { object: notebookOutlineReference } = this.notebookOutlineReference = this.instantiationService.invokeFunction((accessor) => accessor.get(INotebookCellOutlineProviderFactory).getOrCreate(this.notebookEditor, OutlineTarget.QuickPick)); + const { object: notebookOutlineReference } = this.notebookOutlineReference = this.instantiationService.invokeFunction((accessor) => accessor.get(INotebookCellOutlineProviderFactory).getOrCreate(this.notebookEditor, OutlineTarget.OutlinePane)); this._register(this.notebookOutlineReference); this.updateContent(computeContent(this.notebookEditor, this.notebookCellList, notebookOutlineReference.entries, this.getCurrentStickyHeight()));