Merge branch 'main' into merogge/select

This commit is contained in:
Megan Rogge
2023-04-04 19:21:56 -07:00
committed by GitHub
23 changed files with 109 additions and 419 deletions
@@ -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());
+70
View File
@@ -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>;
}
}