mirror of
https://github.com/microsoft/vscode.git
synced 2026-05-08 17:19:48 +01:00
Merge branch 'main' into merogge/select
This commit is contained in:
@@ -38,6 +38,8 @@ steps:
|
||||
stat $ELECTRON_ROOT/chrome-sandbox
|
||||
displayName: Change setuid helper binary permission
|
||||
|
||||
- template: ../common/install-builtin-extensions.yml
|
||||
|
||||
- ${{ if eq(parameters.VSCODE_RUN_UNIT_TESTS, true) }}:
|
||||
- ${{ if eq(parameters.VSCODE_QUALITY, 'oss') }}:
|
||||
- script: ./scripts/test.sh --tfs "Unit Tests"
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 5.8 KiB |
@@ -1562,59 +1562,6 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"walkthroughs": [
|
||||
{
|
||||
"id": "nodejsWelcome",
|
||||
"title": "%walkthroughs.nodejsWelcome.title%",
|
||||
"icon": "media/nodejsWalkthroughIcon.png",
|
||||
"description": "%walkthroughs.nodejsWelcome.description%",
|
||||
"when": "false",
|
||||
"steps": [
|
||||
{
|
||||
"id": "walkthroughs.nodejsWelcome.downloadNode.forMacOrWindows",
|
||||
"title": "%walkthroughs.nodejsWelcome.downloadNode.forMacOrWindows.title%",
|
||||
"description": "%walkthroughs.nodejsWelcome.downloadNode.forMacOrWindows.description%",
|
||||
"media": {
|
||||
"svg": "resources/walkthroughs/install-node-js.svg"
|
||||
},
|
||||
"when": "isWindows || isMac"
|
||||
},
|
||||
{
|
||||
"id": "walkthroughs.nodejsWelcome.downloadNode.forLinux",
|
||||
"title": "%walkthroughs.nodejsWelcome.downloadNode.forLinux.title%",
|
||||
"description": "%walkthroughs.nodejsWelcome.downloadNode.forLinux.description%",
|
||||
"media": {
|
||||
"svg": "resources/walkthroughs/install-node-js.svg"
|
||||
},
|
||||
"when": "isLinux"
|
||||
},
|
||||
{
|
||||
"id": "walkthroughs.nodejsWelcome.makeJsFile",
|
||||
"title": "%walkthroughs.nodejsWelcome.makeJsFile.title%",
|
||||
"description": "%walkthroughs.nodejsWelcome.makeJsFile.description%",
|
||||
"media": {
|
||||
"svg": "resources/walkthroughs/create-a-js-file.svg"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "walkthroughs.nodejsWelcome.debugJsFile",
|
||||
"title": "%walkthroughs.nodejsWelcome.debugJsFile.title%",
|
||||
"description": "%walkthroughs.nodejsWelcome.debugJsFile.description%",
|
||||
"media": {
|
||||
"svg": "resources/walkthroughs/debug-and-run.svg"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "walkthroughs.nodejsWelcome.learnMoreAboutJs",
|
||||
"title": "%walkthroughs.nodejsWelcome.learnMoreAboutJs.title%",
|
||||
"description": "%walkthroughs.nodejsWelcome.learnMoreAboutJs.description%",
|
||||
"media": {
|
||||
"svg": "resources/walkthroughs/learn-more.svg"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"repository": {
|
||||
|
||||
@@ -18,7 +18,7 @@ export class ExperimentationService {
|
||||
|
||||
constructor(telemetryReporter: IExperimentationTelemetryReporter, id: string, version: string, globalState: vscode.Memento) {
|
||||
this._telemetryReporter = telemetryReporter;
|
||||
this._experimentationServicePromise = createExperimentationService(this._telemetryReporter, id, version, globalState);
|
||||
this._experimentationServicePromise = createTasExperimentationService(this._telemetryReporter, id, version, globalState);
|
||||
}
|
||||
|
||||
public async getTreatmentVariable<K extends keyof ExperimentTypes>(name: K, defaultValue: ExperimentTypes[K]): Promise<ExperimentTypes[K]> {
|
||||
@@ -32,7 +32,7 @@ export class ExperimentationService {
|
||||
}
|
||||
}
|
||||
|
||||
export async function createExperimentationService(
|
||||
export async function createTasExperimentationService(
|
||||
reporter: IExperimentationTelemetryReporter,
|
||||
id: string,
|
||||
version: string,
|
||||
|
||||
@@ -17,7 +17,6 @@ import { NodeLogDirectoryProvider } from './tsServer/logDirectoryProvider.electr
|
||||
import { ElectronServiceProcessFactory } from './tsServer/serverProcess.electron';
|
||||
import { DiskTypeScriptVersionProvider } from './tsServer/versionProvider.electron';
|
||||
import { ActiveJsTsEditorTracker } from './ui/activeJsTsEditorTracker';
|
||||
import { JsWalkthroughState, registerJsNodeWalkthrough } from './ui/jsNodeWalkthrough.electron';
|
||||
import { ElectronServiceConfigurationProvider } from './configuration/configuration.electron';
|
||||
import { onCaseInsensitiveFileSystem } from './utils/fs.electron';
|
||||
import { Logger } from './logging/logger';
|
||||
@@ -43,9 +42,6 @@ export function activate(
|
||||
const activeJsTsEditorTracker = new ActiveJsTsEditorTracker();
|
||||
context.subscriptions.push(activeJsTsEditorTracker);
|
||||
|
||||
const jsWalkthroughState = new JsWalkthroughState();
|
||||
context.subscriptions.push(jsWalkthroughState);
|
||||
|
||||
let experimentTelemetryReporter: IExperimentationTelemetryReporter | undefined;
|
||||
const packageInfo = getPackageInfo(context);
|
||||
if (packageInfo) {
|
||||
@@ -77,7 +73,6 @@ export function activate(
|
||||
});
|
||||
|
||||
registerBaseCommands(commandManager, lazyClientHost, pluginManager, activeJsTsEditorTracker);
|
||||
registerJsNodeWalkthrough(commandManager, jsWalkthroughState);
|
||||
|
||||
import('./task/taskProvider').then(module => {
|
||||
context.subscriptions.push(module.register(lazyClientHost.map(x => x.serviceClient)));
|
||||
|
||||
@@ -1,198 +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 * as cp from 'child_process';
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
import { CommandManager } from '../commands/commandManager';
|
||||
import { Disposable } from '../utils/dispose';
|
||||
|
||||
|
||||
export async function nodeWasResolvable(): Promise<boolean> {
|
||||
let execStr: string;
|
||||
switch (process.platform) {
|
||||
case 'win32':
|
||||
execStr = 'where node';
|
||||
break;
|
||||
case 'aix':
|
||||
case 'cygwin':
|
||||
case 'darwin':
|
||||
case 'freebsd':
|
||||
case 'haiku':
|
||||
case 'linux':
|
||||
case 'netbsd':
|
||||
case 'openbsd':
|
||||
case 'sunos':
|
||||
execStr = 'which node';
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return new Promise(resolve => {
|
||||
cp.exec(execStr, { windowsHide: true }, err => {
|
||||
resolve(!err);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export class JsWalkthroughState extends Disposable {
|
||||
exampleJsDocument: vscode.TextDocument | undefined = undefined;
|
||||
|
||||
override dispose() {
|
||||
this.exampleJsDocument = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
export class CreateNewJSFileCommand {
|
||||
public static readonly id = 'javascript-walkthrough.commands.createJsFile';
|
||||
public readonly id = CreateNewJSFileCommand.id;
|
||||
|
||||
constructor(
|
||||
private readonly walkthroughState: JsWalkthroughState
|
||||
) { }
|
||||
|
||||
public execute() {
|
||||
createNewJSFile(this.walkthroughState);
|
||||
}
|
||||
}
|
||||
|
||||
export class DebugJsFileCommand {
|
||||
public static readonly id = 'javascript-walkthrough.commands.debugJsFile';
|
||||
public readonly id = DebugJsFileCommand.id;
|
||||
|
||||
constructor(
|
||||
private readonly walkthroughState: JsWalkthroughState
|
||||
) { }
|
||||
|
||||
public execute() {
|
||||
debugJsFile(this.walkthroughState);
|
||||
}
|
||||
}
|
||||
|
||||
export class NodeInstallationFoundCommand {
|
||||
public static readonly id = 'javascript-walkthrough.commands.nodeInstallationFound';
|
||||
public readonly id = NodeInstallationFoundCommand.id;
|
||||
public execute() { }
|
||||
}
|
||||
|
||||
async function createNewJSFile(walkthroughState: JsWalkthroughState) {
|
||||
const newFile = await vscode.workspace.openTextDocument({
|
||||
language: 'javascript',
|
||||
content: `// Write a message to the console.\nconsole.log('hello world!');\n`,
|
||||
});
|
||||
walkthroughState.exampleJsDocument = newFile;
|
||||
return vscode.window.showTextDocument(newFile, vscode.ViewColumn.Beside);
|
||||
}
|
||||
|
||||
async function debugJsFile(walkthroughState: JsWalkthroughState) {
|
||||
const hasNode = await nodeWasResolvable();
|
||||
if (!hasNode) {
|
||||
const reloadResponse = vscode.l10n.t("Reload VS Code");
|
||||
const debugAnywayResponse = vscode.l10n.t("Try Debugging Anyway");
|
||||
const dismissResponse = vscode.l10n.t("Dismiss");
|
||||
const response = await vscode.window.showErrorMessage(
|
||||
// The message
|
||||
vscode.l10n.t("We couldn\'t find Node.js on this computer. If you just installed it, you might need to reload VS Code."),
|
||||
// The options
|
||||
reloadResponse,
|
||||
debugAnywayResponse,
|
||||
dismissResponse,
|
||||
);
|
||||
|
||||
if (response === undefined || response === dismissResponse) {
|
||||
return;
|
||||
}
|
||||
if (response === reloadResponse) {
|
||||
vscode.commands.executeCommand('workbench.action.reloadWindow');
|
||||
return;
|
||||
}
|
||||
}
|
||||
tryDebugRelevantDocument(walkthroughState.exampleJsDocument, 'javascript', ['.mjs', '.js'], () => createNewJSFile(walkthroughState));
|
||||
}
|
||||
|
||||
type DocSearchResult =
|
||||
| { kind: 'visible'; editor: vscode.TextEditor }
|
||||
| { kind: 'hidden'; uri: vscode.Uri }
|
||||
| { kind: 'not-found' };
|
||||
|
||||
async function tryDebugRelevantDocument(lastDocument: vscode.TextDocument | undefined, languageId: string, languageExtensions: [string, ...string[]], createFileAndFocus: () => Promise<vscode.TextEditor>): Promise<void> {
|
||||
let searchResult!: DocSearchResult;
|
||||
for (const languageExtension of languageExtensions) {
|
||||
searchResult = tryFindRelevantDocument(lastDocument, languageId, languageExtension);
|
||||
if (searchResult.kind !== 'not-found') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let editor: vscode.TextEditor;
|
||||
// If not, make one.
|
||||
switch (searchResult.kind) {
|
||||
case 'visible':
|
||||
// Focus if necessary.
|
||||
editor = searchResult.editor;
|
||||
if (vscode.window.activeTextEditor !== editor) {
|
||||
await vscode.window.showTextDocument(editor.document, {
|
||||
viewColumn: vscode.ViewColumn.Beside,
|
||||
});
|
||||
}
|
||||
break;
|
||||
case 'hidden':
|
||||
editor = await vscode.window.showTextDocument(searchResult.uri, {
|
||||
viewColumn: vscode.ViewColumn.Beside,
|
||||
});
|
||||
break;
|
||||
case 'not-found':
|
||||
editor = await createFileAndFocus();
|
||||
break;
|
||||
}
|
||||
|
||||
await Promise.all([
|
||||
vscode.commands.executeCommand('workbench.action.debug.start'),
|
||||
vscode.commands.executeCommand('workbench.debug.action.focusRepl'),
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
/** Tries to find a relevant {@link vscode.TextEditor} or a {@link vscode.Uri} for an open document */
|
||||
function tryFindRelevantDocument(lastDocument: vscode.TextDocument | undefined, languageId: string, languageExtension: string): DocSearchResult {
|
||||
let editor: vscode.TextEditor | undefined;
|
||||
|
||||
// Try to find the document created from the last step.
|
||||
if (lastDocument) {
|
||||
editor = vscode.window.visibleTextEditors.find(editor => editor.document === lastDocument);
|
||||
}
|
||||
|
||||
// If we couldn't find that, find a visible document with the desired language.
|
||||
editor ??= vscode.window.visibleTextEditors.find(editor => editor.document.languageId === languageId);
|
||||
if (editor) {
|
||||
return {
|
||||
kind: 'visible',
|
||||
editor,
|
||||
};
|
||||
}
|
||||
|
||||
// If we still couldn't find that, find a possibly not-visible document.
|
||||
for (const tabGroup of vscode.window.tabGroups.all) {
|
||||
for (const tab of tabGroup.tabs) {
|
||||
if (tab.input instanceof vscode.TabInputText && tab.input.uri.path.endsWith(languageExtension)) {
|
||||
return {
|
||||
kind: 'hidden',
|
||||
uri: tab.input.uri,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return { kind: 'not-found' };
|
||||
}
|
||||
|
||||
export function registerJsNodeWalkthrough(
|
||||
commandManager: CommandManager,
|
||||
jsWalkthroughState: JsWalkthroughState,
|
||||
) {
|
||||
commandManager.register(new CreateNewJSFileCommand(jsWalkthroughState));
|
||||
commandManager.register(new DebugJsFileCommand(jsWalkthroughState));
|
||||
}
|
||||
@@ -12,7 +12,6 @@ import { IQuickInputService, IQuickInputButton, IQuickPickItem, IQuickPick, IInp
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility';
|
||||
import { EditorScopedLayoutService } from 'vs/editor/standalone/browser/standaloneLayoutService';
|
||||
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
|
||||
import { IQuickInputControllerHost, QuickInputController } from 'vs/platform/quickinput/browser/quickInput';
|
||||
@@ -29,10 +28,9 @@ class EditorScopedQuickInputService extends QuickInputService {
|
||||
@IInstantiationService instantiationService: IInstantiationService,
|
||||
@IContextKeyService contextKeyService: IContextKeyService,
|
||||
@IThemeService themeService: IThemeService,
|
||||
@IAccessibilityService accessibilityService: IAccessibilityService,
|
||||
@ICodeEditorService codeEditorService: ICodeEditorService
|
||||
) {
|
||||
super(instantiationService, contextKeyService, themeService, accessibilityService, new EditorScopedLayoutService(editor.getContainerDomNode(), codeEditorService));
|
||||
super(instantiationService, contextKeyService, themeService, new EditorScopedLayoutService(editor.getContainerDomNode(), codeEditorService));
|
||||
|
||||
// Use the passed in code editor as host for the quick input widget
|
||||
const contribution = QuickInputEditorContribution.get(editor);
|
||||
|
||||
@@ -40,7 +40,6 @@ export interface IQuickInputOptions {
|
||||
idPrefix: string;
|
||||
container: HTMLElement;
|
||||
ignoreFocusOut(): boolean;
|
||||
isScreenReaderOptimized(): boolean;
|
||||
backKeybindingLabel(): string | undefined;
|
||||
setContextKey(id?: string): void;
|
||||
linkOpenerDelegate(content: string): void;
|
||||
@@ -114,10 +113,8 @@ interface QuickInputUI {
|
||||
onDidTriggerButton: Event<IQuickInputButton>;
|
||||
ignoreFocusOut: boolean;
|
||||
keyMods: Writeable<IKeyMods>;
|
||||
isScreenReaderOptimized(): boolean;
|
||||
show(controller: QuickInput): void;
|
||||
setVisibilities(visibilities: Visibilities): void;
|
||||
setComboboxAccessibility(enabled: boolean): void;
|
||||
setEnabled(enabled: boolean): void;
|
||||
setContextKey(contextKey?: string): void;
|
||||
linkOpenerDelegate(content: string): void;
|
||||
@@ -928,7 +925,7 @@ class QuickPick<T extends IQuickPickItem> extends QuickInput implements IQuickPi
|
||||
this.visibleDisposables.add(this.registerQuickNavigation());
|
||||
this.valueSelectionUpdated = true;
|
||||
}
|
||||
super.show(); // TODO: Why have show() bubble up while update() trickles down? (Could move setComboboxAccessibility() here.)
|
||||
super.show(); // TODO: Why have show() bubble up while update() trickles down?
|
||||
}
|
||||
|
||||
private handleAccept(inBackground: boolean): void {
|
||||
@@ -1039,8 +1036,8 @@ class QuickPick<T extends IQuickPickItem> extends QuickInput implements IQuickPi
|
||||
ariaLabel += ` - ${this.title}`;
|
||||
}
|
||||
}
|
||||
if (this.ui.inputBox.ariaLabel !== ariaLabel) {
|
||||
this.ui.inputBox.ariaLabel = ariaLabel;
|
||||
if (this.ui.list.ariaLabel !== ariaLabel) {
|
||||
this.ui.list.ariaLabel = ariaLabel;
|
||||
}
|
||||
this.ui.list.matchOnDescription = this.matchOnDescription;
|
||||
this.ui.list.matchOnDetail = this.matchOnDetail;
|
||||
@@ -1054,10 +1051,6 @@ class QuickPick<T extends IQuickPickItem> extends QuickInput implements IQuickPi
|
||||
this.ui.checkAll.checked = this.ui.list.getAllVisibleChecked();
|
||||
this.ui.visibleCount.setCount(this.ui.list.getVisibleCount());
|
||||
this.ui.count.setCount(this.ui.list.getCheckedCount());
|
||||
// Ensure no item is focused when using a screenreader when items update (#57501 & #166920 & #176848)
|
||||
if (this.ui.isScreenReaderOptimized() && ariaLabel && visibilities.inputBox) {
|
||||
this._itemActivation = ItemActivation.NONE;
|
||||
}
|
||||
switch (this._itemActivation) {
|
||||
case ItemActivation.NONE:
|
||||
this._itemActivation = ItemActivation.FIRST; // only valid once, then unset
|
||||
@@ -1104,7 +1097,6 @@ class QuickPick<T extends IQuickPickItem> extends QuickInput implements IQuickPi
|
||||
}
|
||||
this.ui.customButton.label = this.customLabel || '';
|
||||
this.ui.customButton.element.title = this.customHover || '';
|
||||
this.ui.setComboboxAccessibility(true);
|
||||
if (!visibilities.inputBox) {
|
||||
// we need to move focus into the tree to detect keybindings
|
||||
// properly when the input box is not visible (quick nav)
|
||||
@@ -1235,7 +1227,6 @@ export class QuickInputController extends Disposable {
|
||||
private ui: QuickInputUI | undefined;
|
||||
private dimension?: dom.IDimension;
|
||||
private titleBarOffset?: number;
|
||||
private comboboxAccessibility = false;
|
||||
private enabled = true;
|
||||
private readonly onDidAcceptEmitter = this._register(new Emitter<void>());
|
||||
private readonly onDidCustomEmitter = this._register(new Emitter<void>());
|
||||
@@ -1345,7 +1336,12 @@ export class QuickInputController extends Disposable {
|
||||
const progressBar = new ProgressBar(container, this.styles.progressBar);
|
||||
progressBar.getContainer().classList.add('quick-input-progress');
|
||||
|
||||
const list = this._register(new QuickInputList(container, this.idPrefix + 'list', this.options));
|
||||
const listId = this.idPrefix + 'list';
|
||||
const list = this._register(new QuickInputList(container, listId, this.options));
|
||||
inputBox.setAttribute('aria-controls', listId);
|
||||
this._register(list.onDidChangeFocus(() => {
|
||||
inputBox.setAttribute('aria-activedescendant', list.getActiveDescendant() ?? '');
|
||||
}));
|
||||
this._register(list.onChangedAllVisibleChecked(checked => {
|
||||
checkAll.checked = checked;
|
||||
}));
|
||||
@@ -1364,11 +1360,6 @@ export class QuickInputController extends Disposable {
|
||||
}
|
||||
}, 0);
|
||||
}));
|
||||
this._register(list.onDidChangeFocus(() => {
|
||||
if (this.comboboxAccessibility) {
|
||||
this.getUI().inputBox.setAttribute('aria-activedescendant', this.getUI().list.getActiveDescendant() || '');
|
||||
}
|
||||
}));
|
||||
|
||||
const focusTracker = dom.trackFocus(container);
|
||||
this._register(focusTracker);
|
||||
@@ -1459,11 +1450,9 @@ export class QuickInputController extends Disposable {
|
||||
onDidTriggerButton: this.onDidTriggerButtonEmitter.event,
|
||||
ignoreFocusOut: false,
|
||||
keyMods: this.keyMods,
|
||||
isScreenReaderOptimized: () => this.options.isScreenReaderOptimized(),
|
||||
show: controller => this.show(controller),
|
||||
hide: () => this.hide(),
|
||||
setVisibilities: visibilities => this.setVisibilities(visibilities),
|
||||
setComboboxAccessibility: enabled => this.setComboboxAccessibility(enabled),
|
||||
setEnabled: enabled => this.setEnabled(enabled),
|
||||
setContextKey: contextKey => this.options.setContextKey(contextKey),
|
||||
linkOpenerDelegate: content => this.options.linkOpenerDelegate(content)
|
||||
@@ -1694,8 +1683,6 @@ export class QuickInputController extends Disposable {
|
||||
ui.list.matchOnLabel = true;
|
||||
ui.list.sortByLabel = true;
|
||||
ui.ignoreFocusOut = false;
|
||||
this.setComboboxAccessibility(false);
|
||||
ui.inputBox.ariaLabel = '';
|
||||
ui.inputBox.toggles = undefined;
|
||||
|
||||
const backKeybindingLabel = this.options.backKeybindingLabel();
|
||||
@@ -1725,24 +1712,6 @@ export class QuickInputController extends Disposable {
|
||||
this.updateLayout(); // TODO
|
||||
}
|
||||
|
||||
private setComboboxAccessibility(enabled: boolean) {
|
||||
if (enabled !== this.comboboxAccessibility) {
|
||||
const ui = this.getUI();
|
||||
this.comboboxAccessibility = enabled;
|
||||
if (this.comboboxAccessibility) {
|
||||
ui.inputBox.setAttribute('role', 'combobox');
|
||||
ui.inputBox.setAttribute('aria-haspopup', 'true');
|
||||
ui.inputBox.setAttribute('aria-autocomplete', 'list');
|
||||
ui.inputBox.setAttribute('aria-activedescendant', ui.list.getActiveDescendant() || '');
|
||||
} else {
|
||||
ui.inputBox.removeAttribute('role');
|
||||
ui.inputBox.removeAttribute('aria-haspopup');
|
||||
ui.inputBox.removeAttribute('aria-autocomplete');
|
||||
ui.inputBox.removeAttribute('aria-activedescendant');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private setEnabled(enabled: boolean) {
|
||||
if (enabled !== this.enabled) {
|
||||
this.enabled = enabled;
|
||||
|
||||
@@ -28,6 +28,11 @@ export class QuickInputBox extends Disposable {
|
||||
super();
|
||||
this.container = dom.append(this.parent, $('.quick-input-box'));
|
||||
this.findInput = this._register(new FindInput(this.container, undefined, { label: '', inputBoxStyles, toggleStyles }));
|
||||
const input = this.findInput.inputBox.inputElement;
|
||||
input.role = 'combobox';
|
||||
input.ariaHasPopup = 'menu';
|
||||
input.ariaAutoComplete = 'list';
|
||||
input.ariaExpanded = 'true';
|
||||
}
|
||||
|
||||
onKeyDown = (handler: (event: StandardKeyboardEvent) => void): IDisposable => {
|
||||
@@ -74,14 +79,6 @@ export class QuickInputBox extends Disposable {
|
||||
this.findInput.inputBox.setPlaceHolder(placeholder);
|
||||
}
|
||||
|
||||
get ariaLabel() {
|
||||
return this.findInput.inputBox.getAriaLabel();
|
||||
}
|
||||
|
||||
set ariaLabel(ariaLabel: string) {
|
||||
this.findInput.inputBox.setAriaLabel(ariaLabel);
|
||||
}
|
||||
|
||||
get password() {
|
||||
return this.findInput.inputBox.inputElement.type === 'password';
|
||||
}
|
||||
|
||||
@@ -325,7 +325,6 @@ export class QuickInputList {
|
||||
) {
|
||||
this.id = id;
|
||||
this.container = dom.append(this.parent, $('.quick-input-list'));
|
||||
|
||||
const delegate = new ListElementDelegate();
|
||||
const accessibilityProvider = new QuickInputAccessibilityProvider();
|
||||
this.list = options.createList('QuickInput', this.container, delegate, [new ListElementRenderer()], {
|
||||
@@ -464,6 +463,14 @@ export class QuickInputList {
|
||||
this.list.scrollTop = scrollTop;
|
||||
}
|
||||
|
||||
get ariaLabel() {
|
||||
return this.list.getHTMLElement().ariaLabel;
|
||||
}
|
||||
|
||||
set ariaLabel(label: string | null) {
|
||||
this.list.getHTMLElement().ariaLabel = label;
|
||||
}
|
||||
|
||||
getAllVisibleChecked() {
|
||||
return this.allVisibleChecked(this.elements, false);
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ import { IListRenderer, IListVirtualDelegate } from 'vs/base/browser/ui/list/lis
|
||||
import { List } from 'vs/base/browser/ui/list/listWidget';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility';
|
||||
import { IContextKey, IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { ILayoutService } from 'vs/platform/layout/browser/layoutService';
|
||||
@@ -60,7 +59,6 @@ export class QuickInputService extends Themable implements IQuickInputService {
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
@IContextKeyService protected readonly contextKeyService: IContextKeyService,
|
||||
@IThemeService themeService: IThemeService,
|
||||
@IAccessibilityService private readonly accessibilityService: IAccessibilityService,
|
||||
@ILayoutService protected readonly layoutService: ILayoutService
|
||||
) {
|
||||
super(themeService);
|
||||
@@ -71,7 +69,6 @@ export class QuickInputService extends Themable implements IQuickInputService {
|
||||
idPrefix: 'quickInput_',
|
||||
container: host.container,
|
||||
ignoreFocusOut: () => false,
|
||||
isScreenReaderOptimized: () => this.accessibilityService.isScreenReaderOptimized(),
|
||||
backKeybindingLabel: () => undefined,
|
||||
setContextKey: (id?: string) => this.setContextKey(id),
|
||||
linkOpenerDelegate: (content) => {
|
||||
|
||||
@@ -46,7 +46,6 @@ suite('QuickInput', () => { // https://github.com/microsoft/vscode/issues/147543
|
||||
container: fixture,
|
||||
idPrefix: 'testQuickInput',
|
||||
ignoreFocusOut() { return true; },
|
||||
isScreenReaderOptimized() { return false; },
|
||||
returnFocus() { },
|
||||
backKeybindingLabel() { return undefined; },
|
||||
setContextKey() { return undefined; },
|
||||
|
||||
@@ -957,7 +957,6 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
return extHostNotebookDocuments.onDidChangeNotebookDocument(listener, thisArg, disposables);
|
||||
},
|
||||
onWillSaveNotebookDocument(listener, thisArg, disposables) {
|
||||
checkProposedApiEnabled(extension, 'notebookDocumentWillSave');
|
||||
return extHostNotebookDocumentSaveParticipant.getOnWillSaveNotebookDocumentEvent(extension)(listener, thisArg, disposables);
|
||||
},
|
||||
get onDidOpenNotebookDocument(): Event<vscode.NotebookDocument> {
|
||||
|
||||
@@ -53,7 +53,7 @@ export class ExtHostNotebookDocumentSaveParticipant implements ExtHostNotebookDo
|
||||
|
||||
const edits: WorkspaceEdit[] = [];
|
||||
|
||||
await this._onWillSaveNotebookDocumentEvent.fireAsync({ document: document.apiNotebook, reason: TextDocumentSaveReason.to(reason) }, token, async (thenable: Promise<unknown>, listener) => {
|
||||
await this._onWillSaveNotebookDocumentEvent.fireAsync({ notebook: document.apiNotebook, reason: TextDocumentSaveReason.to(reason) }, token, async (thenable: Promise<unknown>, listener) => {
|
||||
const now = Date.now();
|
||||
const data = await await Promise.resolve(thenable);
|
||||
if (Date.now() - now > this._thresholds.timeout) {
|
||||
|
||||
@@ -2416,9 +2416,9 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditorD
|
||||
}
|
||||
}
|
||||
|
||||
if (includeOutput) {
|
||||
for (let i = 0; i < this.getLength(); i++) {
|
||||
const cell = this.cellAt(i);
|
||||
if (includeOutput && this._list) {
|
||||
for (let i = 0; i < this._list.length; i++) {
|
||||
const cell = this._list.element(i);
|
||||
|
||||
if (cell?.cellKind === CellKind.Code) {
|
||||
requests.push(this._warmupCell((cell as CodeCellViewModel)));
|
||||
|
||||
@@ -199,10 +199,9 @@ export class BackLayerWebView<T extends ICommonCellInfo> extends Themable {
|
||||
}
|
||||
|
||||
this._register(workspaceTrustManagementService.onDidChangeTrust(e => {
|
||||
this._sendMessageToWebview({
|
||||
type: 'updateWorkspaceTrust',
|
||||
isTrusted: e,
|
||||
});
|
||||
const baseUrl = this.asWebviewUri(this.getNotebookBaseUri(), undefined);
|
||||
const htmlContent = this.generateContent(baseUrl.toString());
|
||||
this.webview?.setHtml(htmlContent);
|
||||
}));
|
||||
|
||||
this._register(TokenizationRegistry.onDidChange(() => {
|
||||
|
||||
@@ -378,10 +378,6 @@ export interface INotebookOptionsMessage {
|
||||
readonly renderOptions: RenderOptions;
|
||||
}
|
||||
|
||||
export interface INotebookUpdateWorkspaceTrust {
|
||||
readonly type: 'updateWorkspaceTrust';
|
||||
readonly isTrusted: boolean;
|
||||
}
|
||||
export interface ITokenizedCodeBlockMessage {
|
||||
readonly type: 'tokenizedCodeBlock';
|
||||
readonly codeBlockId: string;
|
||||
@@ -529,7 +525,6 @@ export type ToWebviewMessage = IClearMessage |
|
||||
IInitializeMarkupCells |
|
||||
INotebookStylesMessage |
|
||||
INotebookOptionsMessage |
|
||||
INotebookUpdateWorkspaceTrust |
|
||||
ITokenizedCodeBlockMessage |
|
||||
ITokenizedStylesChangedMessage |
|
||||
IFindMessage |
|
||||
|
||||
@@ -90,7 +90,7 @@ async function webviewPreloads(ctx: PreloadContext) {
|
||||
const textDecoder = new TextDecoder();
|
||||
|
||||
let currentOptions = ctx.options;
|
||||
let isWorkspaceTrusted = ctx.isWorkspaceTrusted;
|
||||
const isWorkspaceTrusted = ctx.isWorkspaceTrusted;
|
||||
let currentRenderOptions = ctx.renderOptions;
|
||||
const settingChange: EmitterLike<RenderOptions> = createEmitter<RenderOptions>();
|
||||
|
||||
@@ -1397,11 +1397,6 @@ async function webviewPreloads(ctx: PreloadContext) {
|
||||
currentRenderOptions = event.data.renderOptions;
|
||||
settingChange.fire(currentRenderOptions);
|
||||
break;
|
||||
case 'updateWorkspaceTrust': {
|
||||
isWorkspaceTrusted = event.data.isTrusted;
|
||||
viewModel.rerender();
|
||||
break;
|
||||
}
|
||||
case 'tokenizedCodeBlock': {
|
||||
const { codeBlockId, html } = event.data;
|
||||
MarkdownCodeBlock.highlightCodeBlock(codeBlockId, html);
|
||||
@@ -1870,11 +1865,6 @@ async function webviewPreloads(ctx: PreloadContext) {
|
||||
this._outputCells.clear();
|
||||
}
|
||||
|
||||
public rerender() {
|
||||
this.rerenderMarkupCells();
|
||||
this.renderOutputCells();
|
||||
}
|
||||
|
||||
private async createMarkupCell(init: webviewMessages.IMarkupCellInitialization, top: number, visible: boolean): Promise<MarkupCell> {
|
||||
const existing = this._markupCells.get(init.cellId);
|
||||
if (existing) {
|
||||
@@ -1929,12 +1919,6 @@ async function webviewPreloads(ctx: PreloadContext) {
|
||||
cell?.unhide();
|
||||
}
|
||||
|
||||
private rerenderMarkupCells() {
|
||||
for (const cell of this._markupCells.values()) {
|
||||
cell.rerender();
|
||||
}
|
||||
}
|
||||
|
||||
private getExpectedMarkupCell(id: string): MarkupCell | undefined {
|
||||
const cell = this._markupCells.get(id);
|
||||
if (!cell) {
|
||||
@@ -1966,12 +1950,6 @@ async function webviewPreloads(ctx: PreloadContext) {
|
||||
}
|
||||
}
|
||||
|
||||
private renderOutputCells() {
|
||||
for (const outputCell of this._outputCells.values()) {
|
||||
outputCell.rerender();
|
||||
}
|
||||
}
|
||||
|
||||
public async renderOutputCell(data: webviewMessages.ICreationRequestMessage, signal: AbortSignal): Promise<void> {
|
||||
const preloadErrors = await Promise.all<undefined | Error>(
|
||||
data.requiredPreloads.map(p => kernelPreloads.waitFor(p.uri).then(() => undefined, err => err))
|
||||
@@ -2266,10 +2244,6 @@ async function webviewPreloads(ctx: PreloadContext) {
|
||||
this.updateMarkupDimensions();
|
||||
}
|
||||
|
||||
public rerender() {
|
||||
this.updateContentAndRender(this._content.value, this._content.metadata);
|
||||
}
|
||||
|
||||
public remove() {
|
||||
this.element.remove();
|
||||
}
|
||||
@@ -2378,12 +2352,6 @@ async function webviewPreloads(ctx: PreloadContext) {
|
||||
this.outputElements.get(outputId)?.updateContentAndRender(content);
|
||||
}
|
||||
|
||||
public rerender() {
|
||||
for (const outputElement of this.outputElements.values()) {
|
||||
outputElement.rerender();
|
||||
}
|
||||
}
|
||||
|
||||
public updateOutputHeight(outputId: string, height: number) {
|
||||
this.outputElements.get(outputId)?.updateHeight(height);
|
||||
}
|
||||
@@ -2458,10 +2426,6 @@ async function webviewPreloads(ctx: PreloadContext) {
|
||||
return this._outputNode;
|
||||
}
|
||||
|
||||
public rerender() {
|
||||
this._outputNode?.rerender();
|
||||
}
|
||||
|
||||
public updateContentAndRender(content: webviewMessages.ICreationContent) {
|
||||
this._outputNode?.updateAndRerender(content);
|
||||
}
|
||||
@@ -2490,7 +2454,6 @@ async function webviewPreloads(ctx: PreloadContext) {
|
||||
class OutputElement {
|
||||
public readonly element: HTMLElement;
|
||||
private _content?: {
|
||||
readonly content: webviewMessages.ICreationContent;
|
||||
readonly preferredRendererId: string | undefined;
|
||||
readonly preloadErrors: ReadonlyArray<Error | undefined>;
|
||||
};
|
||||
@@ -2528,7 +2491,7 @@ async function webviewPreloads(ctx: PreloadContext) {
|
||||
this.renderTaskAbort?.abort();
|
||||
this.renderTaskAbort = undefined;
|
||||
|
||||
this._content = { content, preferredRendererId, preloadErrors };
|
||||
this._content = { preferredRendererId, preloadErrors };
|
||||
if (content.type === 0 /* RenderOutputType.Html */) {
|
||||
const trustedHtml = ttPolicy?.createHTML(content.htmlContent) ?? content.htmlContent;
|
||||
this.element.innerHTML = trustedHtml as string;
|
||||
@@ -2586,16 +2549,9 @@ async function webviewPreloads(ctx: PreloadContext) {
|
||||
}
|
||||
}
|
||||
|
||||
public rerender() {
|
||||
if (this._content) {
|
||||
this.render(this._content.content, this._content.preferredRendererId, this._content.preloadErrors);
|
||||
}
|
||||
}
|
||||
|
||||
public updateAndRerender(content: webviewMessages.ICreationContent) {
|
||||
if (this._content) {
|
||||
this._content = { content, preferredRendererId: this._content.preferredRendererId, preloadErrors: this._content.preloadErrors };
|
||||
this.rerender();
|
||||
this.render(content, this._content.preferredRendererId, this._content.preloadErrors);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +48,6 @@ export const allApiProposals = Object.freeze({
|
||||
notebookCellExecutionState: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.notebookCellExecutionState.d.ts',
|
||||
notebookControllerAffinityHidden: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.notebookControllerAffinityHidden.d.ts',
|
||||
notebookDeprecated: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.notebookDeprecated.d.ts',
|
||||
notebookDocumentWillSave: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.notebookDocumentWillSave.d.ts',
|
||||
notebookKernelSource: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.notebookKernelSource.d.ts',
|
||||
notebookLiveShare: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.notebookLiveShare.d.ts',
|
||||
notebookMessaging: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.notebookMessaging.d.ts',
|
||||
|
||||
@@ -9,7 +9,6 @@ import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility';
|
||||
import { QuickInputController } from 'vs/platform/quickinput/browser/quickInput';
|
||||
import { QuickInputService as BaseQuickInputService } from 'vs/platform/quickinput/browser/quickInputService';
|
||||
import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
@@ -29,11 +28,10 @@ export class QuickInputService extends BaseQuickInputService {
|
||||
@IKeybindingService private readonly keybindingService: IKeybindingService,
|
||||
@IContextKeyService contextKeyService: IContextKeyService,
|
||||
@IThemeService themeService: IThemeService,
|
||||
@IAccessibilityService accessibilityService: IAccessibilityService,
|
||||
@ILayoutService layoutService: ILayoutService,
|
||||
@IHoverService private readonly hoverService: IHoverService
|
||||
) {
|
||||
super(instantiationService, contextKeyService, themeService, accessibilityService, layoutService);
|
||||
super(instantiationService, contextKeyService, themeService, layoutService);
|
||||
|
||||
this.registerListeners();
|
||||
}
|
||||
|
||||
@@ -320,7 +320,7 @@ export function workbenchInstantiationService(
|
||||
instantiationService.stub(IPaneCompositePartService, new TestPaneCompositeService());
|
||||
instantiationService.stub(IListService, new TestListService());
|
||||
const hoverService = instantiationService.stub(IHoverService, instantiationService.createInstance(TestHoverService));
|
||||
instantiationService.stub(IQuickInputService, disposables.add(new QuickInputService(configService, instantiationService, keybindingService, contextKeyService, themeService, accessibilityService, layoutService, hoverService)));
|
||||
instantiationService.stub(IQuickInputService, disposables.add(new QuickInputService(configService, instantiationService, keybindingService, contextKeyService, themeService, layoutService, hoverService)));
|
||||
instantiationService.stub(IWorkspacesService, new TestWorkspacesService());
|
||||
instantiationService.stub(IWorkspaceTrustManagementService, new TestWorkspaceTrustManagementService());
|
||||
instantiationService.stub(ITerminalInstanceService, new TestTerminalInstanceService());
|
||||
|
||||
Vendored
+70
@@ -12489,6 +12489,21 @@ declare module 'vscode' {
|
||||
*/
|
||||
export const onDidChangeNotebookDocument: Event<NotebookDocumentChangeEvent>;
|
||||
|
||||
/**
|
||||
* An event that is emitted when a {@link NotebookDocument notebook document} will be saved to disk.
|
||||
*
|
||||
* *Note 1:* Subscribers can delay saving by registering asynchronous work. For the sake of data integrity the editor
|
||||
* might save without firing this event. For instance when shutting down with dirty files.
|
||||
*
|
||||
* *Note 2:* Subscribers are called sequentially and they can {@link NotebookDocumentWillSaveEvent.waitUntil delay} saving
|
||||
* by registering asynchronous work. Protection against misbehaving listeners is implemented as such:
|
||||
* * there is an overall time budget that all listeners share and if that is exhausted no further listener is called
|
||||
* * listeners that take a long time or produce errors frequently will not be called anymore
|
||||
*
|
||||
* The current thresholds are 1.5 seconds as overall time budget and a listener can misbehave 3 times before being ignored.
|
||||
*/
|
||||
export const onWillSaveNotebookDocument: Event<NotebookDocumentWillSaveEvent>;
|
||||
|
||||
/**
|
||||
* An event that is emitted when a {@link NotebookDocument notebook} is saved.
|
||||
*/
|
||||
@@ -13558,6 +13573,61 @@ declare module 'vscode' {
|
||||
readonly cellChanges: readonly NotebookDocumentCellChange[];
|
||||
}
|
||||
|
||||
/**
|
||||
* An event that is fired when a {@link NotebookDocument notebook document} will be saved.
|
||||
*
|
||||
* To make modifications to the document before it is being saved, call the
|
||||
* {@linkcode NotebookDocumentWillSaveEvent.waitUntil waitUntil}-function with a thenable
|
||||
* that resolves to a {@link WorkspaceEdit workspace edit}.
|
||||
*/
|
||||
export interface NotebookDocumentWillSaveEvent {
|
||||
/**
|
||||
* A cancellation token.
|
||||
*/
|
||||
readonly token: CancellationToken;
|
||||
|
||||
/**
|
||||
* The {@link NotebookDocument notebook document} that will be saved.
|
||||
*/
|
||||
readonly notebook: NotebookDocument;
|
||||
|
||||
/**
|
||||
* The reason why save was triggered.
|
||||
*/
|
||||
readonly reason: TextDocumentSaveReason;
|
||||
|
||||
/**
|
||||
* Allows to pause the event loop and to apply {@link WorkspaceEdit workspace edit}.
|
||||
* Edits of subsequent calls to this function will be applied in order. The
|
||||
* edits will be *ignored* if concurrent modifications of the notebook document happened.
|
||||
*
|
||||
* *Note:* This function can only be called during event dispatch and not
|
||||
* in an asynchronous manner:
|
||||
*
|
||||
* ```ts
|
||||
* workspace.onWillSaveNotebookDocument(event => {
|
||||
* // async, will *throw* an error
|
||||
* setTimeout(() => event.waitUntil(promise));
|
||||
*
|
||||
* // sync, OK
|
||||
* event.waitUntil(promise);
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* @param thenable A thenable that resolves to {@link WorkspaceEdit workspace edit}.
|
||||
*/
|
||||
waitUntil(thenable: Thenable<WorkspaceEdit>): void;
|
||||
|
||||
/**
|
||||
* Allows to pause the event loop until the provided thenable resolved.
|
||||
*
|
||||
* *Note:* This function can only be called during event dispatch.
|
||||
*
|
||||
* @param thenable A thenable that delays saving.
|
||||
*/
|
||||
waitUntil(thenable: Thenable<any>): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* The summary of a notebook cell execution.
|
||||
*/
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
declare module 'vscode' {
|
||||
/**
|
||||
* An event that is fired when a {@link NotebookDocument document} will be saved.
|
||||
*
|
||||
* To make modifications to the document before it is being saved, call the
|
||||
* {@linkcode NotebookDocumentWillSaveEvent.waitUntil waitUntil}-function with a thenable
|
||||
* that resolves to an array of {@link TextEdit text edits}.
|
||||
*/
|
||||
export interface NotebookDocumentWillSaveEvent {
|
||||
/**
|
||||
* A cancellation token.
|
||||
*/
|
||||
readonly token: CancellationToken;
|
||||
|
||||
/**
|
||||
* The document that will be saved.
|
||||
*/
|
||||
readonly document: NotebookDocument;
|
||||
|
||||
/**
|
||||
* The reason why save was triggered.
|
||||
*/
|
||||
readonly reason: TextDocumentSaveReason;
|
||||
|
||||
waitUntil(thenable: Thenable<WorkspaceEdit>): void;
|
||||
|
||||
waitUntil(thenable: Thenable<any>): void;
|
||||
}
|
||||
|
||||
export namespace workspace {
|
||||
|
||||
export const onWillSaveNotebookDocument: Event<NotebookDocumentWillSaveEvent>;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user