Merge branch 'master' into sandy081/web-playground/login

This commit is contained in:
Sandeep Somavarapu 2020-09-15 17:31:42 +02:00 committed by GitHub
commit a4a9fcb7dd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
135 changed files with 1141 additions and 827 deletions

View file

@ -73,6 +73,7 @@ RUN apt-get update \
libnss3 \
libxss1 \
libasound2 \
libgbm1 \
xfonts-base \
xfonts-terminus \
fonts-noto \

View file

@ -4,24 +4,24 @@
# Excluding: *.test.ts
# ContextLines: 3
26 results - 15 files
22 results - 14 files
src/vs/base/browser/markdownRenderer.ts:
156 const strValue = values[0];
157 const span = element.querySelector(`div[data-code="${id}"]`);
158 if (span) {
159: span.innerHTML = strValue;
160 }
161 }).catch(err => {
162 // ignore
161 const strValue = values[0];
162 const span = element.querySelector(`div[data-code="${id}"]`);
163 if (span) {
164: span.innerHTML = strValue;
165 }
166 }).catch(err => {
167 // ignore
238 return true;
239 }
240
241: element.innerHTML = insane(renderedMarkdown, {
242 allowedSchemes,
243 // allowedTags should included everything that markdown renders to.
244 // Since we have our own sanitize function for marked, it's possible we missed some tag so let insane make sure.
243 return true;
244 }
245
246: element.innerHTML = insane(renderedMarkdown, {
247 allowedSchemes,
248 // allowedTags should included everything that markdown renders to.
249 // Since we have our own sanitize function for marked, it's possible we missed some tag so let insane make sure.
src/vs/base/browser/ui/contextview/contextview.ts:
157 this.shadowRootHostElement = DOM.$('.shadow-root-host');
@ -32,47 +32,14 @@ src/vs/base/browser/ui/contextview/contextview.ts:
162 ${SHADOW_ROOT_CSS}
163 </style>
src/vs/code/electron-browser/workbench/workbench.js:
124 const style = document.createElement('style');
125 style.className = 'initialShellColors';
126 document.head.appendChild(style);
127: style.innerHTML = `body { background-color: ${shellBackground}; color: ${shellForeground}; margin: 0; padding: 0; }`;
128
129 if (data && data.layoutInfo) {
130 // restore parts if possible (we might not always store layout info)
150
151 if (configuration.folderUri || configuration.workspace) {
152 // folder or workspace -> status bar color, sidebar
153: splash.innerHTML = `
154 <div style="position: absolute; width: 100%; left: 0; top: 0; height: ${layoutInfo.titleBarHeight}px; background-color: ${colorInfo.titleBarBackground}; -webkit-app-region: drag;"></div>
155 <div style="position: absolute; height: calc(100% - ${layoutInfo.titleBarHeight}px); top: ${layoutInfo.titleBarHeight}px; ${layoutInfo.sideBarSide}: 0; width: ${layoutInfo.activityBarWidth}px; background-color: ${colorInfo.activityBarBackground};"></div>
156 <div style="position: absolute; height: calc(100% - ${layoutInfo.titleBarHeight}px); top: ${layoutInfo.titleBarHeight}px; ${layoutInfo.sideBarSide}: ${layoutInfo.activityBarWidth}px; width: ${layoutInfo.sideBarWidth}px; background-color: ${colorInfo.sideBarBackground};"></div>
158 `;
159 } else {
160 // empty -> speical status bar color, no sidebar
161: splash.innerHTML = `
162 <div style="position: absolute; width: 100%; left: 0; top: 0; height: ${layoutInfo.titleBarHeight}px; background-color: ${colorInfo.titleBarBackground}; -webkit-app-region: drag;"></div>
163 <div style="position: absolute; height: calc(100% - ${layoutInfo.titleBarHeight}px); top: ${layoutInfo.titleBarHeight}px; ${layoutInfo.sideBarSide}: 0; width: ${layoutInfo.activityBarWidth}px; background-color: ${colorInfo.activityBarBackground};"></div>
164 <div style="position: absolute; width: 100%; bottom: 0; left: 0; height: ${layoutInfo.statusBarHeight}px; background-color: ${colorInfo.statusBarNoFolderBackground};"></div>
src/vs/code/electron-sandbox/issue/issueReporterMain.ts:
57 const platformClass = platform.isWindows ? 'windows' : platform.isLinux ? 'linux' : 'mac';
58 addClass(document.body, platformClass); // used by our fonts
59
60: document.body.innerHTML = BaseHtml();
61 const issueReporter = new IssueReporter(configuration);
62 issueReporter.render();
63 document.body.style.display = 'block';
244 content.push(`.monaco-text-button:not(.disabled):hover, .monaco-text-button:focus { background-color: ${styles.buttonHoverBackground} !important; }`);
245 }
246
247: styleTag.innerHTML = content.join('\n');
248 document.head.appendChild(styleTag);
249 document.body.style.color = styles.color || '';
250 }
57 const platformClass = platform.isWindows ? 'windows' : platform.isLinux ? 'linux' : 'mac';
58 addClass(document.body, platformClass); // used by our fonts
59
60: document.body.innerHTML = BaseHtml();
61 const issueReporter = new IssueReporter(configuration);
62 issueReporter.render();
63 document.body.style.display = 'block';
src/vs/code/electron-sandbox/processExplorer/processExplorerMain.ts:
320 content.push(`.highest { color: ${styles.highlightForeground}; }`);

View file

@ -2,7 +2,7 @@
# Flags: CaseSensitive WordMatch
# ContextLines: 2
14 results - 4 files
12 results - 4 files
src/vs/base/browser/dom.ts:
83 };
@ -24,21 +24,9 @@ src/vs/base/browser/dom.ts:
src/vs/base/common/arrays.ts:
401
402 /**
403: * @deprecated ES6: use `Array.findIndex`
403: * @deprecated ES6: use `Array.find`
404 */
405 export function firstIndex<T>(array: ReadonlyArray<T>, fn: (item: T) => boolean): number {
417
418 /**
419: * @deprecated ES6: use `Array.find`
420 */
421 export function first<T>(array: ReadonlyArray<T>, fn: (item: T) => boolean, notFoundValue: T): T;
568
569 /**
570: * @deprecated ES6: use `Array.find`
571 */
572 export function find<T>(arr: ArrayLike<T>, predicate: (value: T, index: number, arr: ArrayLike<T>) => any): T | undefined {
405 export function first<T>(array: ReadonlyArray<T>, fn: (item: T) => boolean, notFoundValue: T): T;
src/vs/base/common/objects.ts:
115

View file

@ -2,18 +2,52 @@
# Flags: RegExp
# ContextLines: 2
2 results - 2 files
8 results - 4 files
src/vs/base/browser/ui/tree/asyncDataTree.ts:
243 } : () => 'treeitem',
244 isChecked: options.accessibilityProvider!.isChecked ? (e) => {
245: return !!(options.accessibilityProvider?.isChecked!(e.element as T));
246 } : undefined,
247 getAriaLabel(e) {
241 } : () => 'treeitem',
242 isChecked: options.accessibilityProvider!.isChecked ? (e) => {
243: return !!(options.accessibilityProvider?.isChecked!(e.element as T));
244 } : undefined,
245 getAriaLabel(e) {
src/vs/workbench/contrib/debug/browser/debugConfigurationManager.ts:
254
255 return debugDynamicExtensions.map(e => {
256: const type = e.contributes?.debuggers![0].type!;
257 return {
258 label: this.getDebuggerLabel(type)!,
src/vs/platform/list/browser/listService.ts:
463
464 if (typeof options?.openOnSingleClick !== 'boolean' && options?.configurationService) {
465: this.openOnSingleClick = options?.configurationService!.getValue(openModeSettingKey) !== 'doubleClick';
466 this._register(options?.configurationService.onDidChangeConfiguration(() => {
467: this.openOnSingleClick = options?.configurationService!.getValue(openModeSettingKey) !== 'doubleClick';
468 }));
469 } else {
src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts:
1526
1527 await this._ensureActiveKernel();
1528: await this._activeKernel?.cancelNotebookCell!(this._notebookViewModel!.uri, undefined);
1529 }
1530
1535
1536 await this._ensureActiveKernel();
1537: await this._activeKernel?.executeNotebookCell!(this._notebookViewModel!.uri, undefined);
1538 }
1539
1553
1554 await this._ensureActiveKernel();
1555: await this._activeKernel?.cancelNotebookCell!(this._notebookViewModel!.uri, cell.handle);
1556 }
1557
1567
1568 await this._ensureActiveKernel();
1569: await this._activeKernel?.executeNotebookCell!(this._notebookViewModel!.uri, cell.handle);
1570 }
1571
src/vs/workbench/contrib/webview/electron-browser/iframeWebviewElement.ts:
89 .then(() => this._resourceRequestManager.ensureReady())
90 .then(() => {
91: this.element?.contentWindow!.postMessage({ channel, args: data }, '*');
92 });
93 }

View file

@ -14,10 +14,10 @@ resources:
image: vscodehub.azurecr.io/vscode-linux-build-agent:x64
endpoint: VSCodeHub
- container: vscode-arm64
image: vscodehub.azurecr.io/vscode-linux-build-agent:buster-arm64
image: vscodehub.azurecr.io/vscode-linux-build-agent:stretch-arm64
endpoint: VSCodeHub
- container: vscode-armhf
image: vscodehub.azurecr.io/vscode-linux-build-agent:buster-armhf
image: vscodehub.azurecr.io/vscode-linux-build-agent:stretch-armhf
endpoint: VSCodeHub
- container: snapcraft
image: snapcore/snapcraft:stable

View file

@ -206,6 +206,10 @@
"name": "vs/workbench/contrib/webview",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/webviewPanel",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/customEditor",
"project": "vscode-workbench"

View file

@ -507,7 +507,7 @@ suite('Notebook API tests', () => {
// inserting two new cells
{
const edit = new vscode.WorkspaceEdit();
edit.replaceCells(document.uri, 0, 0, [{
edit.replaceNotebookCells(document.uri, 0, 0, [{
cellKind: vscode.CellKind.Markdown,
language: 'markdown',
metadata: undefined,
@ -532,8 +532,8 @@ suite('Notebook API tests', () => {
// deleting cell 1 and 3
{
const edit = new vscode.WorkspaceEdit();
edit.replaceCells(document.uri, 0, 1, []);
edit.replaceCells(document.uri, 2, 3, []);
edit.replaceNotebookCells(document.uri, 0, 1, []);
edit.replaceNotebookCells(document.uri, 2, 3, []);
const success = await vscode.workspace.applyEdit(edit);
assert.strictEqual(success, true);
}
@ -544,7 +544,7 @@ suite('Notebook API tests', () => {
// replacing all cells
{
const edit = new vscode.WorkspaceEdit();
edit.replaceCells(document.uri, 0, 1, [{
edit.replaceNotebookCells(document.uri, 0, 1, [{
cellKind: vscode.CellKind.Markdown,
language: 'markdown',
metadata: undefined,
@ -567,7 +567,7 @@ suite('Notebook API tests', () => {
// remove all cells
{
const edit = new vscode.WorkspaceEdit();
edit.replaceCells(document.uri, 0, document.cells.length, []);
edit.replaceNotebookCells(document.uri, 0, document.cells.length, []);
const success = await vscode.workspace.applyEdit(edit);
assert.strictEqual(success, true);
}
@ -586,7 +586,7 @@ suite('Notebook API tests', () => {
assert.strictEqual(document.cells.length, 1);
const edit = new vscode.WorkspaceEdit();
edit.replaceCells(document.uri, 0, 0, [{
edit.replaceNotebookCells(document.uri, 0, 0, [{
cellKind: vscode.CellKind.Markdown,
language: 'markdown',
metadata: undefined,
@ -1228,6 +1228,43 @@ suite('regression', () => {
// await vscode.commands.executeCommand('workbench.action.closeAllEditors');
// });
test('#106657. Opening a notebook from markers view is broken ', async function () {
assertInitalState();
const resource = await createRandomFile('', undefined, 'first', '.vsctestnb');
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
const document = vscode.notebook.activeNotebookEditor?.document!;
const [cell] = document.cells;
await saveAllFilesAndCloseAll(document.uri);
assert.strictEqual(vscode.notebook.activeNotebookEditor, undefined);
// opening a cell-uri opens a notebook editor
await vscode.commands.executeCommand('vscode.open', cell.uri, vscode.ViewColumn.Active);
assert.strictEqual(!!vscode.notebook.activeNotebookEditor, true);
assert.strictEqual(vscode.notebook.activeNotebookEditor?.document.uri.toString(), resource.toString());
});
test('Cannot open notebook from cell-uri with vscode.open-command', async function () {
this.skip();
assertInitalState();
const resource = await createRandomFile('', undefined, 'first', '.vsctestnb');
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
const document = vscode.notebook.activeNotebookEditor?.document!;
const [cell] = document.cells;
await saveAllFilesAndCloseAll(document.uri);
assert.strictEqual(vscode.notebook.activeNotebookEditor, undefined);
// BUG is that the editor opener (https://github.com/microsoft/vscode/blob/8e7877bdc442f1e83a7fec51920d82b696139129/src/vs/editor/browser/services/openerService.ts#L69)
// removes the fragment if it matches something numeric. For notebooks that's not wanted...
await vscode.commands.executeCommand('vscode.open', cell.uri);
assert.strictEqual(vscode.notebook.activeNotebookEditor?.document.uri.toString(), resource.toString());
});
test('#97830, #97764. Support switch to other editor types', async function () {
assertInitalState();
const resource = await createRandomFile('', undefined, 'empty', '.vsctestnb');

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
<mime-type type="application/x-@@NAME@@-workspace">
<comment>@@NAME_LONG@@ Workspace</comment>
<glob pattern="*.code-workspace"/>
</mime-type>
<mime-type type="application/x-@@NAME@@-workspace">
<comment>@@NAME_LONG@@ Workspace</comment>
<glob pattern="*.code-workspace"/>
</mime-type>
</mime-info>

View file

@ -4,9 +4,10 @@
*--------------------------------------------------------------------------------------------*/
import * as dom from 'vs/base/browser/dom';
import { renderCodiconsRegex } from 'vs/base/common/codicons';
export function renderCodiconsAsElement(text: string): Array<HTMLSpanElement | string> {
const renderCodiconsRegex = /(\\)?\$\((([a-z0-9\-]+?)(?:~([a-z0-9\-]*?))?)\)/gi;
export function renderCodicons(text: string): Array<HTMLSpanElement | string> {
const elements = new Array<HTMLSpanElement | string>();
let match: RegExpMatchArray | null;
@ -24,4 +25,4 @@ export function renderCodiconsAsElement(text: string): Array<HTMLSpanElement | s
elements.push(text.substring(textStart));
}
return elements;
}
}

View file

@ -83,17 +83,17 @@ const _classList: IDomClassList = new class implements IDomClassList {
};
/** @deprecated ES6 - use classList*/
export const hasClass: (node: HTMLElement | SVGElement, className: string) => boolean = _classList.hasClass.bind(_classList);
export function hasClass(node: HTMLElement | SVGElement, className: string): boolean { return _classList.hasClass(node, className); }
/** @deprecated ES6 - use classList*/
export const addClass: (node: HTMLElement | SVGElement, className: string) => void = _classList.addClass.bind(_classList);
export function addClass(node: HTMLElement | SVGElement, className: string): void { return _classList.addClass(node, className); }
/** @deprecated ES6 - use classList*/
export const addClasses: (node: HTMLElement | SVGElement, ...classNames: string[]) => void = _classList.addClasses.bind(_classList);
export function addClasses(node: HTMLElement | SVGElement, ...classNames: string[]): void { return _classList.addClasses(node, ...classNames); }
/** @deprecated ES6 - use classList*/
export const removeClass: (node: HTMLElement | SVGElement, className: string) => void = _classList.removeClass.bind(_classList);
export function removeClass(node: HTMLElement | SVGElement, className: string): void { return _classList.removeClass(node, className); }
/** @deprecated ES6 - use classList*/
export const removeClasses: (node: HTMLElement | SVGElement, ...classNames: string[]) => void = _classList.removeClasses.bind(_classList);
export function removeClasses(node: HTMLElement | SVGElement, ...classNames: string[]): void { return _classList.removeClasses(node, ...classNames); }
/** @deprecated ES6 - use classList*/
export const toggleClass: (node: HTMLElement | SVGElement, className: string, shouldHaveIt?: boolean) => void = _classList.toggleClass.bind(_classList);
export function toggleClass(node: HTMLElement | SVGElement, className: string, shouldHaveIt?: boolean): void { return _classList.toggleClass(node, className, shouldHaveIt); }
class DomListener implements IDisposable {
@ -1277,3 +1277,66 @@ export function triggerDownload(dataOrUri: Uint8Array | URI, name: string): void
// Ensure to remove the element from DOM eventually
setTimeout(() => document.body.removeChild(anchor));
}
export enum DetectedFullscreenMode {
/**
* The document is fullscreen, e.g. because an element
* in the document requested to be fullscreen.
*/
DOCUMENT = 1,
/**
* The browser is fullsreen, e.g. because the user enabled
* native window fullscreen for it.
*/
BROWSER
}
export interface IDetectedFullscreen {
/**
* Figure out if the document is fullscreen or the browser.
*/
mode: DetectedFullscreenMode;
/**
* Wether we know for sure that we are in fullscreen mode or
* it is a guess.
*/
guess: boolean;
}
export function detectFullscreen(): IDetectedFullscreen | null {
// Browser fullscreen: use DOM APIs to detect
if (document.fullscreenElement || (<any>document).webkitFullscreenElement || (<any>document).webkitIsFullScreen) {
return { mode: DetectedFullscreenMode.DOCUMENT, guess: false };
}
// There is no standard way to figure out if the browser
// is using native fullscreen. Via checking on screen
// height and comparing that to window height, we can guess
// it though.
if (window.innerHeight === screen.height) {
// if the height of the window matches the screen height, we can
// safely assume that the browser is fullscreen because no browser
// chrome is taking height away (e.g. like toolbars).
return { mode: DetectedFullscreenMode.BROWSER, guess: false };
}
if (platform.isMacintosh || platform.isLinux) {
// macOS and Linux do not properly report `innerHeight`, only Windows does
if (window.outerHeight === screen.height && window.outerWidth === screen.width) {
// if the height of the browser matches the screen height, we can
// only guess that we are in fullscreen. It is also possible that
// the user has turned off taskbars in the OS and the browser is
// simply able to span the entire size of the screen.
return { mode: DetectedFullscreenMode.BROWSER, guess: true };
}
}
// Not in fullscreen
return null;
}

View file

@ -15,9 +15,10 @@ import { cloneAndChange } from 'vs/base/common/objects';
import { escape } from 'vs/base/common/strings';
import { URI } from 'vs/base/common/uri';
import { Schemas } from 'vs/base/common/network';
import { renderCodicons, markdownEscapeEscapedCodicons } from 'vs/base/common/codicons';
import { markdownEscapeEscapedCodicons } from 'vs/base/common/codicons';
import { resolvePath } from 'vs/base/common/resources';
import { StandardMouseEvent } from 'vs/base/browser/mouseEvent';
import { renderCodicons } from 'vs/base/browser/codicons';
export interface MarkedOptions extends marked.MarkedOptions {
baseUrl?: never;
@ -143,7 +144,11 @@ export function renderMarkdown(markdown: IMarkdownString, options: MarkdownRende
}
};
renderer.paragraph = (text): string => {
return `<p>${markdown.supportThemeIcons ? renderCodicons(text) : text}</p>`;
if (markdown.supportThemeIcons) {
const elements = renderCodicons(text);
text = elements.map(e => typeof e === 'string' ? e : e.outerHTML).join('');
}
return `<p>${text}</p>`;
};
if (options.codeBlockRenderer) {

View file

@ -9,12 +9,12 @@ import * as nls from 'vs/nls';
import { Disposable } from 'vs/base/common/lifecycle';
import { SelectBox, ISelectOptionItem, ISelectBoxOptions } from 'vs/base/browser/ui/selectBox/selectBox';
import { IAction, IActionRunner, Action, IActionChangeEvent, ActionRunner, Separator, IActionViewItem } from 'vs/base/common/actions';
import * as DOM from 'vs/base/browser/dom';
import * as types from 'vs/base/common/types';
import { EventType, Gesture } from 'vs/base/browser/touch';
import { EventType as TouchEventType, Gesture } from 'vs/base/browser/touch';
import { IContextViewProvider } from 'vs/base/browser/ui/contextview/contextview';
import { DataTransfers } from 'vs/base/browser/dnd';
import { isFirefox } from 'vs/base/browser/browser';
import { $, addClasses, addDisposableListener, append, EventHelper, EventLike, EventType, removeClasses, removeTabIndexAndUpdateFocus } from 'vs/base/browser/dom';
export interface IBaseActionViewItemOptions {
draggable?: boolean;
@ -107,19 +107,19 @@ export class BaseActionViewItem extends Disposable implements IActionViewItem {
if (isFirefox) {
// Firefox: requires to set a text data transfer to get going
this._register(DOM.addDisposableListener(container, DOM.EventType.DRAG_START, e => e.dataTransfer?.setData(DataTransfers.TEXT, this._action.label)));
this._register(addDisposableListener(container, EventType.DRAG_START, e => e.dataTransfer?.setData(DataTransfers.TEXT, this._action.label)));
}
}
this._register(DOM.addDisposableListener(element, EventType.Tap, e => this.onClick(e)));
this._register(addDisposableListener(element, TouchEventType.Tap, e => this.onClick(e)));
this._register(DOM.addDisposableListener(element, DOM.EventType.MOUSE_DOWN, e => {
this._register(addDisposableListener(element, EventType.MOUSE_DOWN, e => {
if (!enableDragging) {
DOM.EventHelper.stop(e, true); // do not run when dragging is on because that would disable it
EventHelper.stop(e, true); // do not run when dragging is on because that would disable it
}
if (this._action.enabled && e.button === 0) {
DOM.addClass(element, 'active');
element.classList.add('active');
}
}));
@ -128,15 +128,15 @@ export class BaseActionViewItem extends Disposable implements IActionViewItem {
// main mouse button. This is for scenarios where e.g. some interaction forces
// the Ctrl+key to be pressed and hold but the user still wants to interact
// with the actions (for example quick access in quick navigation mode).
this._register(DOM.addDisposableListener(element, DOM.EventType.CONTEXT_MENU, e => {
this._register(addDisposableListener(element, EventType.CONTEXT_MENU, e => {
if (e.button === 0 && e.ctrlKey === true) {
this.onClick(e);
}
}));
}
this._register(DOM.addDisposableListener(element, DOM.EventType.CLICK, e => {
DOM.EventHelper.stop(e, true);
this._register(addDisposableListener(element, EventType.CLICK, e => {
EventHelper.stop(e, true);
// menus do not use the click event
if (!(this.options && this.options.isMenu)) {
@ -144,20 +144,20 @@ export class BaseActionViewItem extends Disposable implements IActionViewItem {
}
}));
this._register(DOM.addDisposableListener(element, DOM.EventType.DBLCLICK, e => {
DOM.EventHelper.stop(e, true);
this._register(addDisposableListener(element, EventType.DBLCLICK, e => {
EventHelper.stop(e, true);
}));
[DOM.EventType.MOUSE_UP, DOM.EventType.MOUSE_OUT].forEach(event => {
this._register(DOM.addDisposableListener(element, event, e => {
DOM.EventHelper.stop(e);
DOM.removeClass(element, 'active');
[EventType.MOUSE_UP, EventType.MOUSE_OUT].forEach(event => {
this._register(addDisposableListener(element, event, e => {
EventHelper.stop(e);
element.classList.remove('active');
}));
});
}
onClick(event: DOM.EventLike): void {
DOM.EventHelper.stop(event, true);
onClick(event: EventLike): void {
EventHelper.stop(event, true);
const context = types.isUndefinedOrNull(this._context) ? this.options?.useEventAsContext ? event : undefined : this._context;
this.actionRunner.run(this._action, context);
@ -166,14 +166,14 @@ export class BaseActionViewItem extends Disposable implements IActionViewItem {
focus(): void {
if (this.element) {
this.element.focus();
DOM.addClass(this.element, 'focused');
this.element.classList.add('focused');
}
}
blur(): void {
if (this.element) {
this.element.blur();
DOM.removeClass(this.element, 'focused');
this.element.classList.remove('focused');
}
}
@ -199,7 +199,7 @@ export class BaseActionViewItem extends Disposable implements IActionViewItem {
dispose(): void {
if (this.element) {
DOM.removeNode(this.element);
this.element.remove();
this.element = undefined;
}
@ -233,7 +233,7 @@ export class ActionViewItem extends BaseActionViewItem {
super.render(container);
if (this.element) {
this.label = DOM.append(this.element, DOM.$('a.action-label'));
this.label = append(this.element, $('a.action-label'));
}
if (this.label) {
@ -249,7 +249,7 @@ export class ActionViewItem extends BaseActionViewItem {
}
if (this.options.label && this.options.keybinding && this.element) {
DOM.append(this.element, DOM.$('span.keybinding')).textContent = this.options.keybinding;
append(this.element, $('span.keybinding')).textContent = this.options.keybinding;
}
this.updateClass();
@ -294,23 +294,23 @@ export class ActionViewItem extends BaseActionViewItem {
updateClass(): void {
if (this.cssClass && this.label) {
DOM.removeClasses(this.label, this.cssClass);
removeClasses(this.label, this.cssClass);
}
if (this.options.icon) {
this.cssClass = this.getAction().class;
if (this.label) {
DOM.addClass(this.label, 'codicon');
this.label.classList.add('codicon');
if (this.cssClass) {
DOM.addClasses(this.label, this.cssClass);
addClasses(this.label, this.cssClass);
}
}
this.updateEnabled();
} else {
if (this.label) {
DOM.removeClass(this.label, 'codicon');
this.label.classList.remove('codicon');
}
}
}
@ -319,22 +319,22 @@ export class ActionViewItem extends BaseActionViewItem {
if (this.getAction().enabled) {
if (this.label) {
this.label.removeAttribute('aria-disabled');
DOM.removeClass(this.label, 'disabled');
this.label.classList.remove('disabled');
this.label.tabIndex = 0;
}
if (this.element) {
DOM.removeClass(this.element, 'disabled');
this.element.classList.remove('disabled');
}
} else {
if (this.label) {
this.label.setAttribute('aria-disabled', 'true');
DOM.addClass(this.label, 'disabled');
DOM.removeTabIndexAndUpdateFocus(this.label);
this.label.classList.add('disabled');
removeTabIndexAndUpdateFocus(this.label);
}
if (this.element) {
DOM.addClass(this.element, 'disabled');
this.element.classList.add('disabled');
}
}
}
@ -342,9 +342,9 @@ export class ActionViewItem extends BaseActionViewItem {
updateChecked(): void {
if (this.label) {
if (this.getAction().checked) {
DOM.addClass(this.label, 'checked');
this.label.classList.add('checked');
} else {
DOM.removeClass(this.label, 'checked');
this.label.classList.remove('checked');
}
}
}

View file

@ -475,7 +475,7 @@ export class ActionBar extends Disposable implements IActionRunner {
this._actionIds = [];
DOM.removeNode(this.getContainer());
this.getContainer().remove();
super.dispose();
}

View file

@ -4,15 +4,15 @@
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./button';
import * as DOM from 'vs/base/browser/dom';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { KeyCode } from 'vs/base/common/keyCodes';
import { Color } from 'vs/base/common/color';
import { mixin } from 'vs/base/common/objects';
import { Event as BaseEvent, Emitter } from 'vs/base/common/event';
import { Disposable } from 'vs/base/common/lifecycle';
import { Gesture, EventType } from 'vs/base/browser/touch';
import { renderCodiconsAsElement } from 'vs/base/browser/codicons';
import { Gesture, EventType as TouchEventType } from 'vs/base/browser/touch';
import { renderCodicons } from 'vs/base/browser/codicons';
import { addDisposableListener, IFocusTracker, EventType, EventHelper, trackFocus, reset, removeTabIndexAndUpdateFocus } from 'vs/base/browser/dom';
export interface IButtonOptions extends IButtonStyles {
readonly title?: boolean | string;
@ -52,7 +52,7 @@ export class Button extends Disposable {
private _onDidClick = this._register(new Emitter<Event>());
get onDidClick(): BaseEvent<Event> { return this._onDidClick.event; }
private focusTracker: DOM.IFocusTracker;
private focusTracker: IFocusTracker;
constructor(container: HTMLElement, options?: IButtonOptions) {
super();
@ -71,7 +71,7 @@ export class Button extends Disposable {
this.buttonBorder = this.options.buttonBorder;
this._element = document.createElement('a');
DOM.addClass(this._element, 'monaco-button');
this._element.classList.add('monaco-button');
this._element.tabIndex = 0;
this._element.setAttribute('role', 'button');
@ -79,10 +79,10 @@ export class Button extends Disposable {
this._register(Gesture.addTarget(this._element));
[DOM.EventType.CLICK, EventType.Tap].forEach(eventType => {
this._register(DOM.addDisposableListener(this._element, eventType, e => {
[EventType.CLICK, TouchEventType.Tap].forEach(eventType => {
this._register(addDisposableListener(this._element, eventType, e => {
if (!this.enabled) {
DOM.EventHelper.stop(e);
EventHelper.stop(e);
return;
}
@ -90,7 +90,7 @@ export class Button extends Disposable {
}));
});
this._register(DOM.addDisposableListener(this._element, DOM.EventType.KEY_DOWN, e => {
this._register(addDisposableListener(this._element, EventType.KEY_DOWN, e => {
const event = new StandardKeyboardEvent(e);
let eventHandled = false;
if (this.enabled && (event.equals(KeyCode.Enter) || event.equals(KeyCode.Space))) {
@ -102,22 +102,22 @@ export class Button extends Disposable {
}
if (eventHandled) {
DOM.EventHelper.stop(event, true);
EventHelper.stop(event, true);
}
}));
this._register(DOM.addDisposableListener(this._element, DOM.EventType.MOUSE_OVER, e => {
if (!DOM.hasClass(this._element, 'disabled')) {
this._register(addDisposableListener(this._element, EventType.MOUSE_OVER, e => {
if (!this._element.classList.contains('disabled')) {
this.setHoverBackground();
}
}));
this._register(DOM.addDisposableListener(this._element, DOM.EventType.MOUSE_OUT, e => {
this._register(addDisposableListener(this._element, EventType.MOUSE_OUT, e => {
this.applyStyles(); // restore standard styles
}));
// Also set hover background when button is focused for feedback
this.focusTracker = this._register(DOM.trackFocus(this._element));
this.focusTracker = this._register(trackFocus(this._element));
this._register(this.focusTracker.onDidFocus(() => this.setHoverBackground()));
this._register(this.focusTracker.onDidBlur(() => this.applyStyles())); // restore standard styles
@ -175,11 +175,9 @@ export class Button extends Disposable {
}
set label(value: string) {
if (!DOM.hasClass(this._element, 'monaco-text-button')) {
DOM.addClass(this._element, 'monaco-text-button');
}
this._element.classList.add('monaco-text-button');
if (this.options.supportCodicons) {
DOM.reset(this._element, ...renderCodiconsAsElement(value));
reset(this._element, ...renderCodicons(value));
} else {
this._element.textContent = value;
}
@ -191,23 +189,23 @@ export class Button extends Disposable {
}
set icon(iconClassName: string) {
DOM.addClass(this._element, iconClassName);
this._element.classList.add(iconClassName);
}
set enabled(value: boolean) {
if (value) {
DOM.removeClass(this._element, 'disabled');
this._element.classList.remove('disabled');
this._element.setAttribute('aria-disabled', String(false));
this._element.tabIndex = 0;
} else {
DOM.addClass(this._element, 'disabled');
this._element.classList.add('disabled');
this._element.setAttribute('aria-disabled', String(true));
DOM.removeTabIndexAndUpdateFocus(this._element);
removeTabIndexAndUpdateFocus(this._element);
}
}
get enabled() {
return !DOM.hasClass(this._element, 'disabled');
return !this._element.classList.contains('disabled');
}
focus(): void {
@ -235,7 +233,7 @@ export class ButtonGroup extends Disposable {
// Implement keyboard access in buttons if there are multiple
if (count > 1) {
this._register(DOM.addDisposableListener(button.element, DOM.EventType.KEY_DOWN, e => {
this._register(addDisposableListener(button.element, EventType.KEY_DOWN, e => {
const event = new StandardKeyboardEvent(e);
let eventHandled = true;
@ -251,7 +249,7 @@ export class ButtonGroup extends Disposable {
if (eventHandled && typeof buttonIndexToFocus === 'number') {
this._buttons[buttonIndexToFocus].focus();
DOM.EventHelper.stop(e, true);
EventHelper.stop(e, true);
}
}));

View file

@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { reset } from 'vs/base/browser/dom';
import { renderCodiconsAsElement } from 'vs/base/browser/codicons';
import { renderCodicons } from 'vs/base/browser/codicons';
export class CodiconLabel {
@ -13,7 +13,7 @@ export class CodiconLabel {
) { }
set text(text: string) {
reset(this._container, ...renderCodiconsAsElement(text ?? ''));
reset(this._container, ...renderCodicons(text ?? ''));
}
set title(title: string) {

View file

@ -139,7 +139,7 @@ export class ContextView extends Disposable {
if (this.shadowRoot) {
this.shadowRoot.removeChild(this.view);
this.shadowRoot = null;
DOM.removeNode(this.shadowRootHostElement!);
this.shadowRootHostElement?.remove();
this.shadowRootHostElement = null;
} else {
this.container.removeChild(this.view);

View file

@ -10,7 +10,7 @@ import { IDisposable } from 'vs/base/common/lifecycle';
import { IContextViewProvider, IAnchor, AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview';
import { IMenuOptions } from 'vs/base/browser/ui/menu/menu';
import { KeyCode } from 'vs/base/common/keyCodes';
import { EventHelper, EventType, removeClass, addClass, append, $, addDisposableListener, DOMEvent } from 'vs/base/browser/dom';
import { EventHelper, EventType, append, $, addDisposableListener, DOMEvent } from 'vs/base/browser/dom';
import { IContextMenuProvider } from 'vs/base/browser/contextmenu';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { Emitter } from 'vs/base/common/event';
@ -162,7 +162,7 @@ export class Dropdown extends BaseDropdown {
show(): void {
super.show();
addClass(this.element, 'active');
this.element.classList.add('active');
this.contextViewProvider.showContextView({
getAnchor: () => this.getAnchor(),
@ -184,7 +184,7 @@ export class Dropdown extends BaseDropdown {
}
protected onHide(): void {
removeClass(this.element, 'active');
this.element.classList.remove('active');
}
hide(): void {
@ -253,7 +253,7 @@ export class DropdownMenu extends BaseDropdown {
show(): void {
super.show();
addClass(this.element, 'active');
this.element.classList.add('active');
this._contextMenuProvider.showContextMenu({
getAnchor: () => this.element,
@ -275,6 +275,6 @@ export class DropdownMenu extends BaseDropdown {
private onHide(): void {
this.hide();
removeClass(this.element, 'active');
this.element.classList.remove('active');
}
}

View file

@ -8,12 +8,11 @@ import { IAction, IActionRunner, IActionViewItemProvider } from 'vs/base/common/
import { IDisposable } from 'vs/base/common/lifecycle';
import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview';
import { ResolvedKeybinding } from 'vs/base/common/keyCodes';
import { append, $, addClasses } from 'vs/base/browser/dom';
import { append, $ } from 'vs/base/browser/dom';
import { Emitter } from 'vs/base/common/event';
import { BaseActionViewItem, IBaseActionViewItemOptions } from 'vs/base/browser/ui/actionbar/actionViewItems';
import { IActionProvider, DropdownMenu, IDropdownMenuOptions, ILabelRenderer } from 'vs/base/browser/ui/dropdown/dropdown';
import { IContextMenuProvider } from 'vs/base/browser/contextmenu';
import { asArray } from 'vs/base/common/arrays';
export interface IKeybindingProvider {
(action: IAction): ResolvedKeybinding | undefined;
@ -60,14 +59,20 @@ export class DropdownMenuActionViewItem extends BaseActionViewItem {
const labelRenderer: ILabelRenderer = (el: HTMLElement): IDisposable | null => {
this.element = append(el, $('a.action-label'));
const classNames = this.options.classNames ? asArray(this.options.classNames) : [];
let classNames: string[] = [];
if (typeof this.options.classNames === 'string') {
classNames = this.options.classNames.split(/\W+/g).filter(s => !!s);
} else if (this.options.classNames) {
classNames = this.options.classNames;
}
// todo@aeschli: remove codicon, should come through `this.options.classNames`
if (!classNames.find(c => c === 'icon')) {
classNames.push('codicon');
}
addClasses(this.element, ...classNames);
this.element.classList.add(...classNames);
this.element.tabIndex = 0;
this.element.setAttribute('role', 'button');

View file

@ -5,7 +5,7 @@
import * as objects from 'vs/base/common/objects';
import * as dom from 'vs/base/browser/dom';
import { renderCodiconsAsElement } from 'vs/base/browser/codicons';
import { renderCodicons } from 'vs/base/browser/codicons';
export interface IHighlight {
start: number;
@ -61,12 +61,12 @@ export class HighlightedLabel {
}
if (pos < highlight.start) {
const substring = this.text.substring(pos, highlight.start);
children.push(dom.$('span', undefined, ...this.supportCodicons ? renderCodiconsAsElement(substring) : [substring]));
children.push(dom.$('span', undefined, ...this.supportCodicons ? renderCodicons(substring) : [substring]));
pos = highlight.end;
}
const substring = this.text.substring(highlight.start, highlight.end);
const element = dom.$('span.highlight', undefined, ...this.supportCodicons ? renderCodiconsAsElement(substring) : [substring]);
const element = dom.$('span.highlight', undefined, ...this.supportCodicons ? renderCodicons(substring) : [substring]);
if (highlight.extraClasses) {
element.classList.add(highlight.extraClasses);
}
@ -76,7 +76,7 @@ export class HighlightedLabel {
if (pos < this.text.length) {
const substring = this.text.substring(pos,);
children.push(dom.$('span', undefined, ...this.supportCodicons ? renderCodiconsAsElement(substring) : [substring]));
children.push(dom.$('span', undefined, ...this.supportCodicons ? renderCodicons(substring) : [substring]));
}
dom.reset(this.domNode, ...children);

View file

@ -6,7 +6,6 @@
import { getOrDefault } from 'vs/base/common/objects';
import { IDisposable, dispose, Disposable, toDisposable, DisposableStore } from 'vs/base/common/lifecycle';
import { Gesture, EventType as TouchEventType, GestureEvent } from 'vs/base/browser/touch';
import * as DOM from 'vs/base/browser/dom';
import { Event, Emitter } from 'vs/base/common/event';
import { domEvent } from 'vs/base/browser/event';
import { SmoothScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';
@ -22,6 +21,7 @@ import { DataTransfers, StaticDND, IDragAndDropData } from 'vs/base/browser/dnd'
import { disposableTimeout, Delayer } from 'vs/base/common/async';
import { isFirefox } from 'vs/base/browser/browser';
import { IMouseWheelEvent } from 'vs/base/browser/mouseEvent';
import { $, animate, getContentHeight, getContentWidth, getTopLeftOffset, scheduleAtNextAnimationFrame } from 'vs/base/browser/dom';
interface IItem<T> {
readonly id: string;
@ -260,7 +260,7 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
}
this._horizontalScrolling = value;
DOM.toggleClass(this.domNode, 'horizontal-scrolling', this._horizontalScrolling);
this.domNode.classList.toggle('horizontal-scrolling', this._horizontalScrolling);
if (this._horizontalScrolling) {
for (const item of this.items) {
@ -268,7 +268,7 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
}
this.updateScrollWidth();
this.scrollableElement.setScrollDimensions({ width: DOM.getContentWidth(this.domNode) });
this.scrollableElement.setScrollDimensions({ width: getContentWidth(this.domNode) });
this.rowsContainer.style.width = `${Math.max(this.scrollWidth || 0, this.renderWidth)}px`;
} else {
this.scrollableElementWidthDelayer.cancel();
@ -303,13 +303,13 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
this.domNode = document.createElement('div');
this.domNode.className = 'monaco-list';
DOM.addClass(this.domNode, this.domId);
this.domNode.classList.add(this.domId);
this.domNode.tabIndex = 0;
DOM.toggleClass(this.domNode, 'mouse-support', typeof options.mouseSupport === 'boolean' ? options.mouseSupport : true);
this.domNode.classList.toggle('mouse-support', typeof options.mouseSupport === 'boolean' ? options.mouseSupport : true);
this._horizontalScrolling = getOrDefault(options, o => o.horizontalScrolling, DefaultOptions.horizontalScrolling);
DOM.toggleClass(this.domNode, 'horizontal-scrolling', this._horizontalScrolling);
this.domNode.classList.toggle('horizontal-scrolling', this._horizontalScrolling);
this.additionalScrollHeight = typeof options.additionalScrollHeight === 'undefined' ? 0 : options.additionalScrollHeight;
@ -325,7 +325,7 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
this.disposables.add(Gesture.addTarget(this.rowsContainer));
this.scrollable = new Scrollable(getOrDefault(options, o => o.smoothScrolling, false) ? 125 : 0, cb => DOM.scheduleAtNextAnimationFrame(cb));
this.scrollable = new Scrollable(getOrDefault(options, o => o.smoothScrolling, false) ? 125 : 0, cb => scheduleAtNextAnimationFrame(cb));
this.scrollableElement = this.disposables.add(new SmoothScrollableElement(this.rowsContainer, {
alwaysConsumeMouseWheel: true,
horizontal: ScrollbarVisibility.Auto,
@ -510,7 +510,7 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
this.rowsContainer.style.height = `${this._scrollHeight}px`;
if (!this.scrollableElementUpdateDisposable) {
this.scrollableElementUpdateDisposable = DOM.scheduleAtNextAnimationFrame(() => {
this.scrollableElementUpdateDisposable = scheduleAtNextAnimationFrame(() => {
this.scrollableElement.setScrollDimensions({ scrollHeight: this.scrollHeight });
this.updateScrollWidth();
this.scrollableElementUpdateDisposable = null;
@ -629,7 +629,7 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
layout(height?: number, width?: number): void {
let scrollDimensions: INewScrollDimensions = {
height: typeof height === 'number' ? height : DOM.getContentHeight(this.domNode)
height: typeof height === 'number' ? height : getContentHeight(this.domNode)
};
if (this.scrollableElementUpdateDisposable) {
@ -649,7 +649,7 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
if (this.horizontalScrolling) {
this.scrollableElement.setScrollDimensions({
width: typeof width === 'number' ? width : DOM.getContentWidth(this.domNode)
width: typeof width === 'number' ? width : getContentWidth(this.domNode)
});
}
}
@ -754,7 +754,7 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
}
item.row.domNode.style.width = isFirefox ? '-moz-fit-content' : 'fit-content';
item.width = DOM.getContentWidth(item.row.domNode);
item.width = getContentWidth(item.row.domNode);
const style = window.getComputedStyle(item.row.domNode);
if (style.paddingLeft) {
@ -785,7 +785,7 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
item.row!.domNode!.setAttribute('aria-posinset', String(this.accessibilityProvider.getPosInSet(item.element, index)));
item.row!.domNode!.setAttribute('id', this.getElementDomId(index));
DOM.toggleClass(item.row!.domNode!, 'drop-target', item.dropTarget);
item.row!.domNode!.classList.toggle('drop-target', item.dropTarget);
}
private removeItemFromDOM(index: number): void {
@ -936,7 +936,7 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
label = String(elements.length);
}
const dragImage = DOM.$('.monaco-drag-image');
const dragImage = $('.monaco-drag-image');
dragImage.textContent = label;
document.body.appendChild(dragImage);
event.dataTransfer.setDragImage(dragImage, -10, -10);
@ -1017,11 +1017,11 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
this.currentDragFeedbackDisposable.dispose();
if (feedback[0] === -1) { // entire list feedback
DOM.addClass(this.domNode, 'drop-target');
DOM.addClass(this.rowsContainer, 'drop-target');
this.domNode.classList.add('drop-target');
this.rowsContainer.classList.add('drop-target');
this.currentDragFeedbackDisposable = toDisposable(() => {
DOM.removeClass(this.domNode, 'drop-target');
DOM.removeClass(this.rowsContainer, 'drop-target');
this.domNode.classList.remove('drop-target');
this.rowsContainer.classList.remove('drop-target');
});
} else {
for (const index of feedback) {
@ -1029,7 +1029,7 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
item.dropTarget = true;
if (item.row && item.row.domNode) {
DOM.addClass(item.row.domNode, 'drop-target');
item.row.domNode.classList.add('drop-target');
}
}
@ -1039,7 +1039,7 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
item.dropTarget = false;
if (item.row && item.row.domNode) {
DOM.removeClass(item.row.domNode, 'drop-target');
item.row.domNode.classList.remove('drop-target');
}
}
});
@ -1095,8 +1095,8 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
private setupDragAndDropScrollTopAnimation(event: DragEvent): void {
if (!this.dragOverAnimationDisposable) {
const viewTop = DOM.getTopLeftOffset(this.domNode).top;
this.dragOverAnimationDisposable = DOM.animate(this.animateDragAndDropScrollTop.bind(this, viewTop));
const viewTop = getTopLeftOffset(this.domNode).top;
this.dragOverAnimationDisposable = animate(this.animateDragAndDropScrollTop.bind(this, viewTop));
}
this.dragOverAnimationStopDisposable.dispose();

View file

@ -8,7 +8,6 @@ import { IDisposable, dispose, DisposableStore } from 'vs/base/common/lifecycle'
import { isNumber } from 'vs/base/common/types';
import { range, binarySearch } from 'vs/base/common/arrays';
import { memoize } from 'vs/base/common/decorators';
import * as DOM from 'vs/base/browser/dom';
import * as platform from 'vs/base/common/platform';
import { Gesture } from 'vs/base/browser/touch';
import { KeyCode } from 'vs/base/common/keyCodes';
@ -27,6 +26,7 @@ import { matchesPrefix } from 'vs/base/common/filters';
import { IDragAndDropData } from 'vs/base/browser/dnd';
import { alert } from 'vs/base/browser/ui/aria/aria';
import { IThemable } from 'vs/base/common/styler';
import { createStyleSheet } from 'vs/base/browser/dom';
interface ITraitChangeEvent {
indexes: number[];
@ -137,11 +137,11 @@ class Trait<T> implements ISpliceable<boolean>, IDisposable {
}
renderIndex(index: number, container: HTMLElement): void {
DOM.toggleClass(container, this._trait, this.contains(index));
container.classList.toggle(this._trait, this.contains(index));
}
unrender(container: HTMLElement): void {
DOM.removeClass(container, this._trait);
container.classList.remove(this._trait);
}
/**
@ -230,11 +230,11 @@ export function isInputElement(e: HTMLElement): boolean {
}
export function isMonacoEditor(e: HTMLElement): boolean {
if (DOM.hasClass(e, 'monaco-editor')) {
if (e.classList.contains('monaco-editor')) {
return true;
}
if (DOM.hasClass(e, 'monaco-list')) {
if (e.classList.contains('monaco-list')) {
return false;
}
@ -1225,7 +1225,7 @@ export class List<T> implements ISpliceable<T>, IThemable, IDisposable {
if (_options.styleController) {
this.styleController = _options.styleController(this.view.domId);
} else {
const styleElement = DOM.createStyleSheet(this.view.domNode);
const styleElement = createStyleSheet(this.view.domNode);
this.styleController = new DefaultStyleController(styleElement, this.view.domId);
}
@ -1633,7 +1633,7 @@ export class List<T> implements ISpliceable<T>, IThemable, IDisposable {
private _onFocusChange(): void {
const focus = this.focus.get();
DOM.toggleClass(this.view.domNode, 'element-focused', focus.length > 0);
this.view.domNode.classList.toggle('element-focused', focus.length > 0);
this.onDidChangeActiveDescendant();
}
@ -1656,9 +1656,9 @@ export class List<T> implements ISpliceable<T>, IThemable, IDisposable {
private _onSelectionChange(): void {
const selection = this.selection.get();
DOM.toggleClass(this.view.domNode, 'selection-none', selection.length === 0);
DOM.toggleClass(this.view.domNode, 'selection-single', selection.length === 1);
DOM.toggleClass(this.view.domNode, 'selection-multiple', selection.length > 1);
this.view.domNode.classList.toggle('selection-none', selection.length === 0);
this.view.domNode.classList.toggle('selection-single', selection.length === 1);
this.view.domNode.classList.toggle('selection-multiple', selection.length > 1);
}
dispose(): void {

View file

@ -5,7 +5,7 @@
import { IListRenderer } from './list';
import { IDisposable } from 'vs/base/common/lifecycle';
import { $, removeClass } from 'vs/base/browser/dom';
import { $ } from 'vs/base/browser/dom';
export interface IRow {
domNode: HTMLElement | null;
@ -60,7 +60,7 @@ export class RowCache<T> implements IDisposable {
private releaseRow(row: IRow): void {
const { domNode, templateId } = row;
if (domNode) {
removeClass(domNode, 'scrolling');
domNode.classList.remove('scrolling');
removeFromParent(domNode);
}

View file

@ -10,7 +10,7 @@ import * as types from 'vs/base/common/types';
import { EventType, GestureEvent, Gesture } from 'vs/base/browser/touch';
import { StandardMouseEvent } from 'vs/base/browser/mouseEvent';
import { Event, Emitter } from 'vs/base/common/event';
import { getElementsByTagName, EventHelper, createStyleSheet, addDisposableListener, append, $, addClass, removeClass, toggleClass } from 'vs/base/browser/dom';
import { getElementsByTagName, EventHelper, createStyleSheet, addDisposableListener, append, $ } from 'vs/base/browser/dom';
import { domEvent } from 'vs/base/browser/event';
const DEBUG = false;
@ -86,9 +86,9 @@ export class Sash extends Disposable {
return;
}
toggleClass(this.el, 'disabled', state === SashState.Disabled);
toggleClass(this.el, 'minimum', state === SashState.Minimum);
toggleClass(this.el, 'maximum', state === SashState.Maximum);
this.el.classList.toggle('disabled', state === SashState.Disabled);
this.el.classList.toggle('minimum', state === SashState.Minimum);
this.el.classList.toggle('maximum', state === SashState.Maximum);
this._state = state;
this._onDidEnablementChange.fire(state);
@ -151,7 +151,7 @@ export class Sash extends Disposable {
this.el = append(container, $('.monaco-sash'));
if (isMacintosh) {
addClass(this.el, 'mac');
this.el.classList.add('mac');
}
this._register(domEvent(this.el, 'mousedown')(this.onMouseDown, this));
@ -185,14 +185,14 @@ export class Sash extends Disposable {
this.orientation = options.orientation || Orientation.VERTICAL;
if (this.orientation === Orientation.HORIZONTAL) {
addClass(this.el, 'horizontal');
removeClass(this.el, 'vertical');
this.el.classList.add('horizontal');
this.el.classList.remove('vertical');
} else {
removeClass(this.el, 'horizontal');
addClass(this.el, 'vertical');
this.el.classList.remove('horizontal');
this.el.classList.add('vertical');
}
toggleClass(this.el, 'debug', DEBUG);
this.el.classList.toggle('debug', DEBUG);
this.layout();
}
@ -238,7 +238,7 @@ export class Sash extends Disposable {
const altKey = mouseDownEvent.altKey;
const startEvent: ISashEvent = { startX, currentX: startX, startY, currentY: startY, altKey };
addClass(this.el, 'active');
this.el.classList.add('active');
this._onDidStart.fire(startEvent);
// fix https://github.com/Microsoft/vscode/issues/21675
@ -290,7 +290,7 @@ export class Sash extends Disposable {
this.el.removeChild(style);
removeClass(this.el, 'active');
this.el.classList.remove('active');
this._onDidEnd.fire();
disposables.dispose();
@ -396,11 +396,11 @@ export class Sash extends Disposable {
}
private onOrthogonalStartSashEnablementChange(state: SashState): void {
toggleClass(this.el, 'orthogonal-start', state !== SashState.Disabled);
this.el.classList.toggle('orthogonal-start', state !== SashState.Disabled);
}
private onOrthogonalEndSashEnablementChange(state: SashState): void {
toggleClass(this.el, 'orthogonal-end', state !== SashState.Disabled);
this.el.classList.toggle('orthogonal-end', state !== SashState.Disabled);
}
private getOrthogonalSash(e: MouseEvent): Sash | undefined {

View file

@ -9,7 +9,7 @@ import { Event, Emitter } from 'vs/base/common/event';
import { domEvent } from 'vs/base/browser/event';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { KeyCode } from 'vs/base/common/keyCodes';
import { $, append, addClass, removeClass, toggleClass, trackFocus, EventHelper, clearNode } from 'vs/base/browser/dom';
import { $, append, trackFocus, EventHelper, clearNode } from 'vs/base/browser/dom';
import { Color, RGBA } from 'vs/base/common/color';
import { SplitView, IView } from './splitview';
import { isFirefox } from 'vs/base/browser/browser';
@ -142,7 +142,7 @@ export abstract class Pane extends Disposable implements IView {
}
if (this.element) {
toggleClass(this.element, 'expanded', expanded);
this.element.classList.toggle('expanded', expanded);
}
this._expanded = !!expanded;
@ -190,8 +190,8 @@ export abstract class Pane extends Disposable implements IView {
this._orientation = orientation;
if (this.element) {
toggleClass(this.element, 'horizontal', this.orientation === Orientation.HORIZONTAL);
toggleClass(this.element, 'vertical', this.orientation === Orientation.VERTICAL);
this.element.classList.toggle('horizontal', this.orientation === Orientation.HORIZONTAL);
this.element.classList.toggle('vertical', this.orientation === Orientation.VERTICAL);
}
if (this.header) {
@ -200,9 +200,9 @@ export abstract class Pane extends Disposable implements IView {
}
render(): void {
toggleClass(this.element, 'expanded', this.isExpanded());
toggleClass(this.element, 'horizontal', this.orientation === Orientation.HORIZONTAL);
toggleClass(this.element, 'vertical', this.orientation === Orientation.VERTICAL);
this.element.classList.toggle('expanded', this.isExpanded());
this.element.classList.toggle('horizontal', this.orientation === Orientation.HORIZONTAL);
this.element.classList.toggle('vertical', this.orientation === Orientation.VERTICAL);
this.header = $('.pane-header');
append(this.element, this.header);
@ -214,8 +214,8 @@ export abstract class Pane extends Disposable implements IView {
const focusTracker = trackFocus(this.header);
this._register(focusTracker);
this._register(focusTracker.onDidFocus(() => addClass(this.header, 'focused'), null));
this._register(focusTracker.onDidBlur(() => removeClass(this.header, 'focused'), null));
this._register(focusTracker.onDidFocus(() => this.header.classList.add('focused'), null));
this._register(focusTracker.onDidBlur(() => this.header.classList.remove('focused'), null));
this.updateHeader();
@ -254,7 +254,7 @@ export abstract class Pane extends Disposable implements IView {
const height = this._orientation === Orientation.VERTICAL ? size - headerSize : this.orthogonalSize - headerSize;
if (this.isExpanded()) {
toggleClass(this.body, 'wide', width >= 600);
this.body.classList.toggle('wide', width >= 600);
this.layoutBody(height, width);
this.expandedSize = size;
}
@ -274,8 +274,8 @@ export abstract class Pane extends Disposable implements IView {
const expanded = !this.headerVisible || this.isExpanded();
this.header.style.lineHeight = `${this.headerSize}px`;
toggleClass(this.header, 'hidden', !this.headerVisible);
toggleClass(this.header, 'expanded', expanded);
this.header.classList.toggle('hidden', !this.headerVisible);
this.header.classList.toggle('expanded', expanded);
this.header.setAttribute('aria-expanded', String(expanded));
this.header.style.color = this.styles.headerForeground ? this.styles.headerForeground.toString() : '';
@ -560,11 +560,11 @@ export class PaneView extends Disposable {
window.clearTimeout(this.animationTimer);
}
addClass(this.el, 'animated');
this.el.classList.add('animated');
this.animationTimer = window.setTimeout(() => {
this.animationTimer = undefined;
removeClass(this.el, 'animated');
this.el.classList.remove('animated');
}, 200);
}

View file

@ -7,12 +7,12 @@ import 'vs/css!./splitview';
import { IDisposable, toDisposable, Disposable, combinedDisposable } from 'vs/base/common/lifecycle';
import { Event, Emitter } from 'vs/base/common/event';
import * as types from 'vs/base/common/types';
import * as dom from 'vs/base/browser/dom';
import { clamp } from 'vs/base/common/numbers';
import { range, pushToStart, pushToEnd } from 'vs/base/common/arrays';
import { Sash, Orientation, ISashEvent as IBaseSashEvent, SashState } from 'vs/base/browser/ui/sash/sash';
import { Color } from 'vs/base/common/color';
import { domEvent } from 'vs/base/browser/event';
import { $, append } from 'vs/base/browser/dom';
export { Orientation } from 'vs/base/browser/ui/sash/sash';
export interface ISplitViewStyles {
@ -93,7 +93,7 @@ abstract class ViewItem<TLayoutContext> {
this.size = 0;
}
dom.toggleClass(this.container, 'visible', visible);
this.container.classList.toggle('visible', visible);
if (this.view.setVisible) {
this.view.setVisible(visible);
@ -122,7 +122,7 @@ abstract class ViewItem<TLayoutContext> {
if (typeof size === 'number') {
this._size = size;
this._cachedVisibleSize = undefined;
dom.addClass(container, 'visible');
container.classList.add('visible');
} else {
this._size = 0;
this._cachedVisibleSize = size.cachedVisibleSize;
@ -296,12 +296,12 @@ export class SplitView<TLayoutContext = undefined> extends Disposable {
this.proportionalLayout = types.isUndefined(options.proportionalLayout) ? true : !!options.proportionalLayout;
this.el = document.createElement('div');
dom.addClass(this.el, 'monaco-split-view2');
dom.addClass(this.el, this.orientation === Orientation.VERTICAL ? 'vertical' : 'horizontal');
this.el.classList.add('monaco-split-view2');
this.el.classList.add(this.orientation === Orientation.VERTICAL ? 'vertical' : 'horizontal');
container.appendChild(this.el);
this.sashContainer = dom.append(this.el, dom.$('.sash-container'));
this.viewContainer = dom.append(this.el, dom.$('.split-view-container'));
this.sashContainer = append(this.el, $('.sash-container'));
this.viewContainer = append(this.el, $('.split-view-container'));
this.style(options.styles || defaultStyles);
@ -323,10 +323,10 @@ export class SplitView<TLayoutContext = undefined> extends Disposable {
style(styles: ISplitViewStyles): void {
if (styles.separatorBorder.isTransparent()) {
dom.removeClass(this.el, 'separator-border');
this.el.classList.remove('separator-border');
this.el.style.removeProperty('--separator-border');
} else {
dom.addClass(this.el, 'separator-border');
this.el.classList.add('separator-border');
this.el.style.setProperty('--separator-border', styles.separatorBorder.toString());
}
}
@ -657,7 +657,7 @@ export class SplitView<TLayoutContext = undefined> extends Disposable {
this.state = State.Busy;
// Add view
const container = dom.$('.split-view-view');
const container = $('.split-view-view');
if (index === this.viewItems.length) {
this.viewContainer.appendChild(container);

View file

@ -72,7 +72,7 @@ export class ToolBar extends Disposable {
actionViewItemProvider: this.options.actionViewItemProvider,
actionRunner: this.actionRunner,
keybindingProvider: this.options.getKeyBinding,
classNames: toolBarMoreIcon.classNames,
classNames: toolBarMoreIcon.classNamesArray,
anchorAlignmentProvider: this.options.anchorAlignmentProvider,
menuAsChild: !!this.options.renderDropdownAsChildElement
}

View file

@ -7,7 +7,7 @@ import 'vs/css!./media/tree';
import { IDisposable, dispose, Disposable, toDisposable, DisposableStore } from 'vs/base/common/lifecycle';
import { IListOptions, List, IListStyles, MouseController, DefaultKeyboardNavigationDelegate, isInputElement, isMonacoEditor } from 'vs/base/browser/ui/list/listWidget';
import { IListVirtualDelegate, IListRenderer, IListMouseEvent, IListContextMenuEvent, IListDragAndDrop, IListDragOverReaction, IKeyboardNavigationLabelProvider, IIdentityProvider, IKeyboardNavigationDelegate } from 'vs/base/browser/ui/list/list';
import { append, $, toggleClass, getDomNodePagePosition, removeClass, addClass, hasClass, hasParentWithClass, createStyleSheet, clearNode, addClasses, removeClasses } from 'vs/base/browser/dom';
import { append, $, getDomNodePagePosition, hasParentWithClass, createStyleSheet, clearNode } from 'vs/base/browser/dom';
import { Event, Relay, Emitter, EventBufferer } from 'vs/base/common/event';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { KeyCode } from 'vs/base/common/keyCodes';
@ -405,10 +405,10 @@ class TreeRenderer<T, TFilterData, TRef, TTemplateData> implements IListRenderer
}
if (node.collapsible && (!this.hideTwistiesOfChildlessElements || node.visibleChildrenCount > 0)) {
addClasses(templateData.twistie, treeItemExpandedIcon.classNames, 'collapsible');
toggleClass(templateData.twistie, 'collapsed', node.collapsed);
templateData.twistie.classList.add(...treeItemExpandedIcon.classNamesArray, 'collapsible');
templateData.twistie.classList.toggle('collapsed', node.collapsed);
} else {
removeClasses(templateData.twistie, treeItemExpandedIcon.classNames, 'collapsible', 'collapsed');
templateData.twistie.classList.remove(...treeItemExpandedIcon.classNamesArray, 'collapsible', 'collapsed');
}
if (node.collapsible) {
@ -443,7 +443,7 @@ class TreeRenderer<T, TFilterData, TRef, TTemplateData> implements IListRenderer
const guide = $<HTMLDivElement>('.indent-guide', { style: `width: ${this.indent}px` });
if (this.activeIndentNodes.has(parent)) {
addClass(guide, 'active');
guide.classList.add('active');
}
if (templateData.indent.childElementCount === 0) {
@ -486,13 +486,13 @@ class TreeRenderer<T, TFilterData, TRef, TTemplateData> implements IListRenderer
this.activeIndentNodes.forEach(node => {
if (!set.has(node)) {
this.renderedIndentGuides.forEach(node, line => removeClass(line, 'active'));
this.renderedIndentGuides.forEach(node, line => line.classList.remove('active'));
}
});
set.forEach(node => {
if (!this.activeIndentNodes.has(node)) {
this.renderedIndentGuides.forEach(node, line => addClass(line, 'active'));
this.renderedIndentGuides.forEach(node, line => line.classList.add('active'));
}
});
@ -833,10 +833,10 @@ class TypeFilterController<T, TFilterData> implements IDisposable {
};
updatePosition();
removeClass(this.domNode, positionClassName);
this.domNode.classList.remove(positionClassName);
addClass(this.domNode, 'dragging');
disposables.add(toDisposable(() => removeClass(this.domNode, 'dragging')));
this.domNode.classList.add('dragging');
disposables.add(toDisposable(() => this.domNode.classList.remove('dragging')));
domEvent(document, 'dragover')(onDragOver, null, disposables);
domEvent(this.domNode, 'dragend')(onDragEnd, null, disposables);
@ -864,12 +864,12 @@ class TypeFilterController<T, TFilterData> implements IDisposable {
private updateFilterOnTypeTitleAndIcon(): void {
if (this.filterOnType) {
removeClasses(this.filterOnTypeDomNode, treeFilterOnTypeOffIcon.classNames);
addClasses(this.filterOnTypeDomNode, treeFilterOnTypeOnIcon.classNames);
this.filterOnTypeDomNode.classList.remove(...treeFilterOnTypeOffIcon.classNamesArray);
this.filterOnTypeDomNode.classList.add(...treeFilterOnTypeOnIcon.classNamesArray);
this.filterOnTypeDomNode.title = localize('disable filter on type', "Disable Filter on Type");
} else {
removeClasses(this.filterOnTypeDomNode, treeFilterOnTypeOnIcon.classNames);
addClasses(this.filterOnTypeDomNode, treeFilterOnTypeOffIcon.classNames);
this.filterOnTypeDomNode.classList.remove(...treeFilterOnTypeOnIcon.classNamesArray);
this.filterOnTypeDomNode.classList.add(...treeFilterOnTypeOffIcon.classNamesArray);
this.filterOnTypeDomNode.title = localize('enable filter on type', "Enable Filter on Type");
}
}
@ -885,7 +885,7 @@ class TypeFilterController<T, TFilterData> implements IDisposable {
this._empty = false;
}
toggleClass(this.domNode, 'no-matches', noMatches);
this.domNode.classList.toggle('no-matches', noMatches);
this.domNode.title = localize('found', "Matched {0} out of {1} elements", this.filter.matchCount, this.filter.totalCount);
this.labelDomNode.textContent = this.pattern.length > 16 ? '…' + this.pattern.substr(this.pattern.length - 16) : this.pattern;
@ -1096,8 +1096,8 @@ class TreeNodeListMouseController<T, TFilterData, TRef> extends MouseController<
}
const target = e.browserEvent.target as HTMLElement;
const onTwistie = hasClass(target, 'monaco-tl-twistie')
|| (hasClass(target, 'monaco-icon-label') && hasClass(target, 'folder-icon') && e.browserEvent.offsetX < 16);
const onTwistie = target.classList.contains('monaco-tl-twistie')
|| (target.classList.contains('monaco-icon-label') && target.classList.contains('folder-icon') && e.browserEvent.offsetX < 16);
let expandOnlyOnTwistieClick = false;
@ -1130,7 +1130,7 @@ class TreeNodeListMouseController<T, TFilterData, TRef> extends MouseController<
}
protected onDoubleClick(e: IListMouseEvent<ITreeNode<T, TFilterData>>): void {
const onTwistie = hasClass(e.browserEvent.target as HTMLElement, 'monaco-tl-twistie');
const onTwistie = (e.browserEvent.target as HTMLElement).classList.contains('monaco-tl-twistie');
if (onTwistie) {
return;
@ -1340,7 +1340,7 @@ export abstract class AbstractTree<T, TFilterData, TRef> implements IDisposable
}
this.styleElement = createStyleSheet(this.view.getHTMLElement());
toggleClass(this.getHTMLElement(), 'always', this._options.renderIndentGuides === RenderIndentGuides.Always);
this.getHTMLElement().classList.toggle('always', this._options.renderIndentGuides === RenderIndentGuides.Always);
}
updateOptions(optionsUpdate: IAbstractTreeOptionsUpdate = {}): void {
@ -1363,7 +1363,7 @@ export abstract class AbstractTree<T, TFilterData, TRef> implements IDisposable
this._onDidUpdateOptions.fire(this._options);
toggleClass(this.getHTMLElement(), 'always', this._options.renderIndentGuides === RenderIndentGuides.Always);
this.getHTMLElement().classList.toggle('always', this._options.renderIndentGuides === RenderIndentGuides.Always);
}
get options(): IAbstractTreeOptions<T, TFilterData> {

View file

@ -15,7 +15,6 @@ import { Iterable } from 'vs/base/common/iterator';
import { IDragAndDropData } from 'vs/base/browser/dnd';
import { ElementsDragAndDropData } from 'vs/base/browser/ui/list/listView';
import { isPromiseCanceledError, onUnexpectedError } from 'vs/base/common/errors';
import { removeClasses, addClasses } from 'vs/base/browser/dom';
import { ScrollEvent } from 'vs/base/common/scrollable';
import { ICompressedTreeNode, ICompressedTreeElement } from 'vs/base/browser/ui/tree/compressedObjectTreeModel';
import { IThemable } from 'vs/base/common/styler';
@ -110,9 +109,9 @@ class AsyncDataTreeRenderer<TInput, T, TFilterData, TTemplateData> implements IT
renderTwistie(element: IAsyncDataTreeNode<TInput, T>, twistieElement: HTMLElement): boolean {
if (element.slow) {
addClasses(twistieElement, treeItemLoadingIcon.classNames);
twistieElement.classList.add(...treeItemLoadingIcon.classNamesArray);
} else {
removeClasses(twistieElement, treeItemLoadingIcon.classNames);
twistieElement.classList.remove(...treeItemLoadingIcon.classNamesArray);
}
return false;
}
@ -1053,9 +1052,9 @@ class CompressibleAsyncDataTreeRenderer<TInput, T, TFilterData, TTemplateData> i
renderTwistie(element: IAsyncDataTreeNode<TInput, T>, twistieElement: HTMLElement): boolean {
if (element.slow) {
addClasses(twistieElement, treeItemLoadingIcon.classNames);
twistieElement.classList.add(...treeItemLoadingIcon.classNamesArray);
} else {
removeClasses(twistieElement, treeItemLoadingIcon.classNames);
twistieElement.classList.remove(...treeItemLoadingIcon.classNamesArray);
}
return false;
}

View file

@ -618,10 +618,10 @@ export class RunOnceScheduler {
private timeout: number;
private timeoutHandler: () => void;
constructor(runner: (...args: any[]) => void, timeout: number) {
constructor(runner: (...args: any[]) => void, delay: number) {
this.timeoutToken = -1;
this.runner = runner;
this.timeout = timeout;
this.timeout = delay;
this.timeoutHandler = this.onTimeout.bind(this);
}
@ -651,6 +651,14 @@ export class RunOnceScheduler {
this.timeoutToken = setTimeout(this.timeoutHandler, delay);
}
get delay(): number {
return this.timeout;
}
set delay(value: number) {
this.timeout = value;
}
/**
* Returns true if scheduled.
*/

View file

@ -501,20 +501,6 @@ export function markdownUnescapeCodicons(text: string): string {
return text.replace(markdownUnescapeCodiconsRegex, (match, escaped, codicon) => escaped ? match : `$(${codicon})`);
}
export const renderCodiconsRegex = /(\\)?\$\((([a-z0-9\-]+?)(?:~([a-z0-9\-]*?))?)\)/gi;
/**
* @deprecated Use `renderCodiconsAsElement` instead
*/
export function renderCodicons(text: string): string {
return text.replace(renderCodiconsRegex, (_, escaped, codicon, name, animation) => {
// If the class for codicons is changed, it should also be updated in src\vs\base\browser\markdownRenderer.ts
return escaped
? `$(${codicon})`
: `<span class="codicon codicon-${name}${animation ? ` codicon-animation-${animation}` : ''}"></span>`;
});
}
const stripCodiconsRegex = /(\s)?(\\)?\$\([a-z0-9\-]+?(?:~[a-z0-9\-]*?)?\)(\s)?/gi;
export function stripCodicons(text: string): string {
if (text.indexOf(codiconStartMarker) === -1) {

View file

@ -12,7 +12,6 @@ export function hash(obj: any): number {
return doHash(obj, 0);
}
export function doHash(obj: any, hashVal: number): number {
switch (typeof obj) {
case 'object':

View file

@ -6,7 +6,7 @@
import { ChildProcess, fork, ForkOptions } from 'child_process';
import { IDisposable, toDisposable, dispose } from 'vs/base/common/lifecycle';
import { Delayer, createCancelablePromise } from 'vs/base/common/async';
import { deepClone, assign } from 'vs/base/common/objects';
import { deepClone } from 'vs/base/common/objects';
import { Emitter, Event } from 'vs/base/common/event';
import { createQueuedSender } from 'vs/base/node/processes';
import { IChannel, ChannelServer as IPCServer, ChannelClient as IPCClient, IChannelClient } from 'vs/base/parts/ipc/common/ipc';
@ -180,10 +180,10 @@ export class Client implements IChannelClient, IDisposable {
const args = this.options && this.options.args ? this.options.args : [];
const forkOpts: ForkOptions = Object.create(null);
forkOpts.env = assign(deepClone(process.env), { 'VSCODE_PARENT_PID': String(process.pid) });
forkOpts.env = { ...deepClone(process.env), 'VSCODE_PARENT_PID': String(process.pid) };
if (this.options && this.options.env) {
forkOpts.env = assign(forkOpts.env, this.options.env);
forkOpts.env = { ...forkOpts.env, ...this.options.env };
}
if (this.options && this.options.freshExecArgv) {

View file

@ -3,43 +3,43 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { renderCodiconsAsElement } from 'vs/base/browser/codicons';
import { renderCodicons } from 'vs/base/browser/codicons';
import * as assert from 'assert';
suite('renderCodicons', () => {
test('no codicons', () => {
const result = renderCodiconsAsElement(' hello World .');
const result = renderCodicons(' hello World .');
assert.equal(elementsToString(result), ' hello World .');
});
test('codicon only', () => {
const result = renderCodiconsAsElement('$(alert)');
const result = renderCodicons('$(alert)');
assert.equal(elementsToString(result), '<span class="codicon codicon-alert"></span>');
});
test('codicon and non-codicon strings', () => {
const result = renderCodiconsAsElement(` $(alert) Unresponsive`);
const result = renderCodicons(` $(alert) Unresponsive`);
assert.equal(elementsToString(result), ' <span class="codicon codicon-alert"></span> Unresponsive');
});
test('multiple codicons', () => {
const result = renderCodiconsAsElement('$(check)$(error)');
const result = renderCodicons('$(check)$(error)');
assert.equal(elementsToString(result), '<span class="codicon codicon-check"></span><span class="codicon codicon-error"></span>');
});
test('escaped codicon', () => {
const result = renderCodiconsAsElement('\\$(escaped)');
const result = renderCodicons('\\$(escaped)');
assert.equal(elementsToString(result), '$(escaped)');
});
test('codicon with animation', () => {
const result = renderCodiconsAsElement('$(zip~anim)');
const result = renderCodicons('$(zip~anim)');
assert.equal(elementsToString(result), '<span class="codicon codicon-zip codicon-animation-anim"></span>');
});

View file

@ -7,7 +7,6 @@ import * as assert from 'assert';
import { ITreeNode, ITreeRenderer, IAsyncDataSource } from 'vs/base/browser/ui/tree/tree';
import { AsyncDataTree } from 'vs/base/browser/ui/tree/asyncDataTree';
import { IListVirtualDelegate, IIdentityProvider } from 'vs/base/browser/ui/list/list';
import { hasClass } from 'vs/base/browser/dom';
import { timeout } from 'vs/base/common/async';
interface Element {
@ -103,8 +102,8 @@ suite('AsyncDataTree', function () {
await tree.setInput(model.root);
assert.equal(container.querySelectorAll('.monaco-list-row').length, 1);
let twistie = container.querySelector('.monaco-list-row:first-child .monaco-tl-twistie') as HTMLElement;
assert(!hasClass(twistie, 'collapsible'));
assert(!hasClass(twistie, 'collapsed'));
assert(!twistie.classList.contains('collapsible'));
assert(!twistie.classList.contains('collapsed'));
model.get('a').children = [
{ id: 'aa' },
@ -151,8 +150,8 @@ suite('AsyncDataTree', function () {
assert.deepStrictEqual(getChildrenCalls, ['root']);
let twistie = container.querySelector('.monaco-list-row:first-child .monaco-tl-twistie') as HTMLElement;
assert(!hasClass(twistie, 'collapsible'));
assert(!hasClass(twistie, 'collapsed'));
assert(!twistie.classList.contains('collapsible'));
assert(!twistie.classList.contains('collapsed'));
assert(tree.getNode().children[0].collapsed);
model.get('a').children = [{ id: 'aa' }, { id: 'ab' }, { id: 'ac' }];
@ -160,8 +159,8 @@ suite('AsyncDataTree', function () {
assert.deepStrictEqual(getChildrenCalls, ['root', 'root']);
twistie = container.querySelector('.monaco-list-row:first-child .monaco-tl-twistie') as HTMLElement;
assert(hasClass(twistie, 'collapsible'));
assert(hasClass(twistie, 'collapsed'));
assert(twistie.classList.contains('collapsible'));
assert(twistie.classList.contains('collapsed'));
assert(tree.getNode().children[0].collapsed);
model.get('a').children = [];
@ -169,8 +168,8 @@ suite('AsyncDataTree', function () {
assert.deepStrictEqual(getChildrenCalls, ['root', 'root', 'root']);
twistie = container.querySelector('.monaco-list-row:first-child .monaco-tl-twistie') as HTMLElement;
assert(!hasClass(twistie, 'collapsible'));
assert(!hasClass(twistie, 'collapsed'));
assert(!twistie.classList.contains('collapsible'));
assert(!twistie.classList.contains('collapsed'));
assert(tree.getNode().children[0].collapsed);
model.get('a').children = [{ id: 'aa' }, { id: 'ab' }, { id: 'ac' }];
@ -178,8 +177,8 @@ suite('AsyncDataTree', function () {
assert.deepStrictEqual(getChildrenCalls, ['root', 'root', 'root', 'root']);
twistie = container.querySelector('.monaco-list-row:first-child .monaco-tl-twistie') as HTMLElement;
assert(hasClass(twistie, 'collapsible'));
assert(hasClass(twistie, 'collapsed'));
assert(twistie.classList.contains('collapsible'));
assert(twistie.classList.contains('collapsed'));
assert(tree.getNode().children[0].collapsed);
});
@ -241,8 +240,8 @@ suite('AsyncDataTree', function () {
await tree.expand(model.get('a'));
let twistie = container.querySelector('.monaco-list-row:first-child .monaco-tl-twistie') as HTMLElement;
assert(hasClass(twistie, 'collapsible'));
assert(!hasClass(twistie, 'collapsed'));
assert(twistie.classList.contains('collapsible'));
assert(!twistie.classList.contains('collapsed'));
assert(!tree.getNode(model.get('a')).collapsed);
tree.collapse(model.get('a'));
@ -250,8 +249,8 @@ suite('AsyncDataTree', function () {
await tree.updateChildren(model.root);
twistie = container.querySelector('.monaco-list-row:first-child .monaco-tl-twistie') as HTMLElement;
assert(!hasClass(twistie, 'collapsible'));
assert(!hasClass(twistie, 'collapsed'));
assert(!twistie.classList.contains('collapsible'));
assert(!twistie.classList.contains('collapsed'));
assert(tree.getNode(model.get('a')).collapsed);
});
@ -387,22 +386,22 @@ suite('AsyncDataTree', function () {
assert.equal(container.querySelectorAll('.monaco-list-row').length, 1);
let twistie = container.querySelector('.monaco-list-row:first-child .monaco-tl-twistie') as HTMLElement;
assert(!hasClass(twistie, 'collapsible'));
assert(!hasClass(twistie, 'collapsed'));
assert(!twistie.classList.contains('collapsible'));
assert(!twistie.classList.contains('collapsed'));
model.get('a').children = [{ id: 'aa' }];
await tree.updateChildren(model.get('a'), false);
assert.equal(container.querySelectorAll('.monaco-list-row').length, 1);
twistie = container.querySelector('.monaco-list-row:first-child .monaco-tl-twistie') as HTMLElement;
assert(hasClass(twistie, 'collapsible'));
assert(hasClass(twistie, 'collapsed'));
assert(twistie.classList.contains('collapsible'));
assert(twistie.classList.contains('collapsed'));
model.get('a').children = [];
await tree.updateChildren(model.get('a'), false);
assert.equal(container.querySelectorAll('.monaco-list-row').length, 1);
twistie = container.querySelector('.monaco-list-row:first-child .monaco-tl-twistie') as HTMLElement;
assert(!hasClass(twistie, 'collapsible'));
assert(!hasClass(twistie, 'collapsed'));
assert(!twistie.classList.contains('collapsible'));
assert(!twistie.classList.contains('collapsed'));
});
test('issues #84569, #82629 - rerender', async () => {

View file

@ -338,7 +338,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
}
focus(options?: { force: boolean }): void {
// macOS: Electron >6.x changed its behaviour to not
// macOS: Electron > 7.x changed its behaviour to not
// bring the application to the foreground when a window
// is focused programmatically. Only via `app.focus` and
// the option `steal: true` can you get the previous

View file

@ -207,10 +207,11 @@ export class LanguageFeatureRequestDelays {
get(model: ITextModel): number {
const key = this._key(model);
return this._clamp(this._cache.get(key)?.value);
const avg = this._cache.get(key);
return this._clamp(avg?.value);
}
update(model: ITextModel, value: number) {
update(model: ITextModel, value: number): number {
const key = this._key(model);
let avg = this._cache.get(key);
if (!avg) {
@ -218,5 +219,6 @@ export class LanguageFeatureRequestDelays {
this._cache.set(key, avg);
}
avg.update(value);
return this.get(model);
}
}

View file

@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { IMarkerService, IMarker, MarkerSeverity, MarkerTag } from 'vs/platform/markers/common/markers';
import { Disposable, toDisposable, IDisposable } from 'vs/base/common/lifecycle';
import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
import { URI } from 'vs/base/common/uri';
import { IModelDeltaDecoration, ITextModel, IModelDecorationOptions, TrackedRangeStickiness, OverviewRulerLane, IModelDecoration, MinimapPosition, IModelDecorationMinimapOptions } from 'vs/editor/common/model';
import { ClassName } from 'vs/editor/common/model/intervalTree';
@ -16,7 +16,6 @@ import { IMarkerDecorationsService } from 'vs/editor/common/services/markersDeco
import { Schemas } from 'vs/base/common/network';
import { Emitter, Event } from 'vs/base/common/event';
import { minimapWarning, minimapError } from 'vs/platform/theme/common/colorRegistry';
import { Delayer } from 'vs/base/common/async';
function MODEL_ID(resource: URI): string {
return resource.toString();
@ -36,10 +35,6 @@ class MarkerDecorations extends Disposable {
}));
}
register<T extends IDisposable>(t: T): T {
return super._register(t);
}
public update(markers: IMarker[], newDecorations: IModelDeltaDecoration[]): boolean {
const oldIds = [...this._markersData.keys()];
this._markersData.clear();
@ -114,8 +109,6 @@ export class MarkerDecorationsService extends Disposable implements IMarkerDecor
private _onModelAdded(model: ITextModel): void {
const markerDecorations = new MarkerDecorations(model);
this._markerDecorations.set(MODEL_ID(model.uri), markerDecorations);
const delayer = markerDecorations.register(new Delayer(100));
markerDecorations.register(model.onDidChangeContent(() => delayer.trigger(() => this._updateDecorations(markerDecorations))));
this._updateDecorations(markerDecorations);
}

View file

@ -160,7 +160,8 @@ export class CodeLensContribution implements IEditorContribution {
this._codeLensCache.put(model, result);
// update moving average
this._getCodeLensModelDelays.update(model, Date.now() - t1);
const newDelay = this._getCodeLensModelDelays.update(model, Date.now() - t1);
scheduler.delay = newDelay;
// render lenses
this._renderCodeLensSymbols(result);
@ -331,7 +332,7 @@ export class CodeLensContribution implements IEditorContribution {
private _resolveCodeLensesInViewportSoon(): void {
const model = this._editor.getModel();
if (model) {
this._resolveCodeLensesScheduler.schedule(this._resolveCodeLensesDelays.get(model));
this._resolveCodeLensesScheduler.schedule();
}
}
@ -391,7 +392,8 @@ export class CodeLensContribution implements IEditorContribution {
this._resolveCodeLensesPromise.then(() => {
// update moving average
this._resolveCodeLensesDelays.update(model, Date.now() - t1);
const newDelay = this._resolveCodeLensesDelays.update(model, Date.now() - t1);
this._resolveCodeLensesScheduler.delay = newDelay;
if (this._currentCodeLensModel) { // update the cached state with new resolved items
this._codeLensCache.put(model, this._currentCodeLensModel);

View file

@ -14,7 +14,7 @@ import { editorCodeLensForeground } from 'vs/editor/common/view/editorColorRegis
import { CodeLensItem } from 'vs/editor/contrib/codelens/codelens';
import { editorActiveLinkForeground } from 'vs/platform/theme/common/colorRegistry';
import { registerThemingParticipant } from 'vs/platform/theme/common/themeService';
import { renderCodiconsAsElement } from 'vs/base/browser/codicons';
import { renderCodicons } from 'vs/base/browser/codicons';
class CodeLensViewZone implements IViewZone {
@ -88,7 +88,7 @@ class CodeLensContentWidget implements IContentWidget {
}
hasSymbol = true;
if (lens.command) {
const title = renderCodiconsAsElement(lens.command.title);
const title = renderCodicons(lens.command.title);
if (lens.command.id) {
children.push(dom.$('a', { id: String(i) }, ...title));
this._commands.set(String(i), lens.command);

View file

@ -47,12 +47,12 @@ export class ColorPickerHeader extends Disposable {
this._register(model.onDidChangeColor(this.onDidChangeColor, this));
this._register(model.onDidChangePresentation(this.onDidChangePresentation, this));
this.pickedColorNode.style.backgroundColor = Color.Format.CSS.format(model.color) || '';
dom.toggleClass(this.pickedColorNode, 'light', model.color.rgba.a < 0.5 ? this.backgroundColor.isLighter() : model.color.isLighter());
this.pickedColorNode.classList.toggle('light', model.color.rgba.a < 0.5 ? this.backgroundColor.isLighter() : model.color.isLighter());
}
private onDidChangeColor(color: Color): void {
this.pickedColorNode.style.backgroundColor = Color.Format.CSS.format(color) || '';
dom.toggleClass(this.pickedColorNode, 'light', color.rgba.a < 0.5 ? this.backgroundColor.isLighter() : color.isLighter());
this.pickedColorNode.classList.toggle('light', color.rgba.a < 0.5 ? this.backgroundColor.isLighter() : color.isLighter());
this.onDidChangePresentation();
}
@ -264,7 +264,7 @@ abstract class Strip extends Disposable {
private onMouseDown(e: MouseEvent): void {
const monitor = this._register(new GlobalMouseMoveMonitor<IStandardMouseMoveEventData>());
const origin = dom.getDomNodePagePosition(this.domNode);
dom.addClass(this.domNode, 'grabbing');
this.domNode.classList.add('grabbing');
if (e.target !== this.slider) {
this.onDidChangeTop(e.offsetY);
@ -276,7 +276,7 @@ abstract class Strip extends Disposable {
this._onColorFlushed.fire();
mouseUpListener.dispose();
monitor.stopMonitoring(true);
dom.removeClass(this.domNode, 'grabbing');
this.domNode.classList.remove('grabbing');
}, true);
}
@ -298,7 +298,7 @@ class OpacityStrip extends Strip {
constructor(container: HTMLElement, model: ColorPickerModel) {
super(container, model);
dom.addClass(this.domNode, 'opacity-strip');
this.domNode.classList.add('opacity-strip');
this._register(model.onDidChangeColor(this.onDidChangeColor, this));
this.onDidChangeColor(this.model.color);
@ -321,7 +321,7 @@ class HueStrip extends Strip {
constructor(container: HTMLElement, model: ColorPickerModel) {
super(container, model);
dom.addClass(this.domNode, 'hue-strip');
this.domNode.classList.add('hue-strip');
}
protected getValue(color: Color): number {

View file

@ -116,7 +116,7 @@ export abstract class FormattingConflicts {
if (selector) {
return await selector(formatter, document, mode);
}
return formatter[0];
return undefined;
}
}

View file

@ -56,6 +56,7 @@ export class CompletionModel {
private _refilterKind: Refilter;
private _filteredItems?: StrictCompletionItem[];
private _isIncomplete?: Set<CompletionItemProvider>;
private _allProvider?: Set<CompletionItemProvider>; // TODO@jrieken merge incomplete and all provider info
private _stats?: ICompletionStats;
constructor(
@ -99,6 +100,11 @@ export class CompletionModel {
return this._filteredItems!;
}
get allProvider(): Set<CompletionItemProvider> {
this._ensureCachedState();
return this._allProvider!;
}
get incomplete(): Set<CompletionItemProvider> {
this._ensureCachedState();
return this._isIncomplete!;
@ -136,6 +142,7 @@ export class CompletionModel {
private _createCachedState(): void {
this._isIncomplete = new Set();
this._allProvider = new Set();
this._stats = { suggestionCount: 0, snippetCount: 0, textCount: 0 };
const { leadingLineContent, characterCountDelta } = this._lineContext;
@ -164,6 +171,7 @@ export class CompletionModel {
if (item.container.incomplete) {
this._isIncomplete.add(item.provider);
}
this._allProvider.add(item.provider);
// 'word' is that remainder of the current line that we
// filter and score against. In theory each suggestion uses a

View file

@ -44,6 +44,7 @@ export interface ISuggestEvent {
export interface SuggestTriggerContext {
readonly auto: boolean;
readonly shy: boolean;
readonly triggerKind?: CompletionTriggerKind;
readonly triggerCharacter?: string;
}
@ -393,16 +394,12 @@ export class SuggestModel implements IDisposable {
this._context = ctx;
// Build context for request
let suggestCtx: CompletionContext;
let suggestCtx: CompletionContext = { triggerKind: context.triggerKind ?? CompletionTriggerKind.Invoke };
if (context.triggerCharacter) {
suggestCtx = {
triggerKind: CompletionTriggerKind.TriggerCharacter,
triggerCharacter: context.triggerCharacter
};
} else if (onlyFrom && onlyFrom.size > 0) {
suggestCtx = { triggerKind: CompletionTriggerKind.TriggerForIncompleteCompletions };
} else {
suggestCtx = { triggerKind: CompletionTriggerKind.Invoke };
}
this._requestToken = new CancellationTokenSource();
@ -558,7 +555,13 @@ export class SuggestModel implements IDisposable {
if (ctx.leadingWord.word.length !== 0 && ctx.leadingWord.startColumn > this._context.leadingWord.startColumn) {
// started a new word while IntelliSense shows -> retrigger
this.trigger({ auto: this._context.auto, shy: false }, true);
// Select those providers have not contributed to this completion model and re-trigger completions for
// them. Also adopt the existing items and merge them into the new completion model
const inactiveProvider = new Set(CompletionProviderRegistry.all(this._editor.getModel()!));
this._completionModel.allProvider.forEach(provider => inactiveProvider.delete(provider));
const items = this._completionModel.adopt(new Set());
this.trigger({ auto: this._context.auto, shy: false }, true, inactiveProvider, items);
return;
}
@ -566,7 +569,7 @@ export class SuggestModel implements IDisposable {
// typed -> moved cursor RIGHT & incomple model & still on a word -> retrigger
const { incomplete } = this._completionModel;
const adopted = this._completionModel.adopt(incomplete);
this.trigger({ auto: this._state === State.Auto, shy: false }, true, incomplete, adopted);
this.trigger({ auto: this._state === State.Auto, shy: false, triggerKind: CompletionTriggerKind.TriggerForIncompleteCompletions }, true, incomplete, adopted);
} else {
// typed -> moved cursor RIGHT -> update UI

View file

@ -815,6 +815,9 @@ suite('SuggestModel - TriggerAndCancelOracle', function () {
disposables.push(CompletionProviderRegistry.register({ scheme: 'test' }, {
provideCompletionItems(doc, pos) {
countB += 1;
if (!doc.getWordUntilPosition(pos).word.startsWith('a')) {
return;
}
return {
incomplete: false,
suggestions: [{
@ -850,7 +853,7 @@ suite('SuggestModel - TriggerAndCancelOracle', function () {
assert.equal(event.completionModel.items[0].textLabel, 'Z aaa');
assert.equal(event.completionModel.items[1].textLabel, 'aaa');
assert.equal(countA, 2); // should we keep the suggestions from the "active" provider?
assert.equal(countA, 1); // should we keep the suggestions from the "active" provider?, Yes! See: #106573
assert.equal(countB, 2);
});
});

View file

@ -95,6 +95,7 @@ export interface INativeEnvironmentService extends IEnvironmentService {
appRoot: string;
userHome: URI;
appSettingsHome: URI;
tmpDir: URI;
userDataPath: string;
machineSettingsResource: URI;
backupHome: string;

View file

@ -44,6 +44,9 @@ export class EnvironmentService implements INativeEnvironmentService {
@memoize
get appSettingsHome(): URI { return URI.file(path.join(this.userDataPath, 'User')); }
@memoize
get tmpDir(): URI { return URI.file(os.tmpdir()); }
@memoize
get userRoamingDataHome(): URI { return this.appSettingsHome; }

View file

@ -34,7 +34,7 @@ import { ExtensionsManifestCache } from 'vs/platform/extensionManagement/node/ex
import { toErrorMessage } from 'vs/base/common/errorMessage';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { isEngineValid } from 'vs/platform/extensions/common/extensionValidator';
import { tmpdir } from 'os';
import { joinPath } from 'vs/base/common/resources';
import { generateUuid } from 'vs/base/common/uuid';
import { IDownloadService } from 'vs/platform/download/common/download';
import { optional, IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
@ -83,7 +83,7 @@ export class ExtensionManagementService extends Disposable implements IExtension
onDidUninstallExtension: Event<DidUninstallExtensionEvent> = this._onDidUninstallExtension.event;
constructor(
@IEnvironmentService environmentService: INativeEnvironmentService,
@IEnvironmentService private readonly environmentService: INativeEnvironmentService,
@IExtensionGalleryService private readonly galleryService: IExtensionGalleryService,
@ILogService private readonly logService: ILogService,
@optional(IDownloadService) private downloadService: IDownloadService,
@ -107,7 +107,7 @@ export class ExtensionManagementService extends Disposable implements IExtension
async zip(extension: ILocalExtension): Promise<URI> {
this.logService.trace('ExtensionManagementService#zip', extension.identifier.id);
const files = await this.collectFiles(extension);
const location = await zip(path.join(tmpdir(), generateUuid()), files);
const location = await zip(joinPath(this.environmentService.tmpDir, generateUuid()).fsPath, files);
return URI.file(location);
}
@ -217,7 +217,7 @@ export class ExtensionManagementService extends Disposable implements IExtension
throw new Error('Download service is not available');
}
const downloadedLocation = URI.file(path.join(tmpdir(), generateUuid()));
const downloadedLocation = joinPath(this.environmentService.tmpDir, generateUuid());
await this.downloadService.download(vsix, downloadedLocation);
return downloadedLocation;
}

View file

@ -73,10 +73,18 @@ export class LaunchMainService implements ILaunchMainService {
async start(args: NativeParsedArgs, userEnv: IProcessEnvironment): Promise<void> {
this.logService.trace('Received data from other instance: ', args, userEnv);
// Since we now start to open a window, make sure the app has focus.
// Focussing a window will not ensure that the application itself
// has focus, so we use the `steal: true` hint to force focus.
app.focus({ steal: true });
// macOS: Electron > 7.x changed its behaviour to not
// bring the application to the foreground when a window
// is focused programmatically. Only via `app.focus` and
// the option `steal: true` can you get the previous
// behaviour back. The only reason to use this option is
// when a window is getting focused while the application
// is not in the foreground and since we got instructed
// to open a new window from another instance, we ensure
// that the app has focus.
if (isMacintosh) {
app.focus({ steal: true });
}
// Check early for open-url which is handled in URL service
const urlsToOpen = parseOpenUrl(args);

View file

@ -3,7 +3,6 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { readdirSync } from 'vs/base/node/pfs';
import { statSync, readFileSync } from 'fs';
import { join } from 'vs/base/common/path';
@ -43,4 +42,4 @@ export function buildTelemetryMessage(appRoot: string, extensionsPath?: string):
contents = readFileSync(join(appRoot, 'telemetry-extensions.json')).toString();
mergeTelemetry(contents, 'vscode-extensions');
return JSON.stringify(mergedTelemetry, null, 4);
}
}

View file

@ -8,7 +8,6 @@ import { URI } from 'vs/base/common/uri';
import { Event } from 'vs/base/common/event';
import { IURLHandler, IOpenURLOptions } from 'vs/platform/url/common/url';
import { CancellationToken } from 'vs/base/common/cancellation';
import { first } from 'vs/base/common/arrays';
export class URLHandlerChannel implements IServerChannel {
@ -54,7 +53,7 @@ export class URLHandlerRouter implements IClientRouter<string> {
if (match) {
const windowId = match[1];
const regex = new RegExp(`window:${windowId}`);
const connection = first(hub.connections, c => regex.test(c.ctx));
const connection = hub.connections.find(c => regex.test(c.ctx));
if (connection) {
return connection;

View file

@ -138,6 +138,8 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ
async stop(): Promise<void> {
if (cancellablePromise) {
cancellablePromise.cancel();
}
if (that.status !== SyncStatus.Idle) {
return that.stop();
}
}

22
src/vs/vscode.d.ts vendored
View file

@ -4700,7 +4700,7 @@ declare module 'vscode' {
* The *effective* value (returned by [`get`](#WorkspaceConfiguration.get)) is computed by overriding or merging the values in the following order.
*
* ```
* `defaultValue`
* `defaultValue` (if defined in `package.json` otherwise derived from the value's type)
* `globalValue` (if defined)
* `workspaceValue` (if defined)
* `workspaceFolderValue` (if defined)
@ -10598,6 +10598,26 @@ declare module 'vscode' {
* resource state.
*/
readonly decorations?: SourceControlResourceDecorations;
/**
* Context value of the resource state. This can be used to contribute resource specific actions.
* For example, if a resource is given a context value as `diffable`. When contributing actions to `scm/resourceState/context`
* using `menus` extension point, you can specify context value for key `scmResourceState` in `when` expressions, like `scmResourceState == diffable`.
* ```
* "contributes": {
* "menus": {
* "scm/resourceState/context": [
* {
* "command": "extension.diff",
* "when": "scmResourceState == diffable"
* }
* ]
* }
* }
* ```
* This will show action `extension.diff` only for resources with `contextValue` is `diffable`.
*/
readonly contextValue?: string;
}
/**

View file

@ -1313,6 +1313,7 @@ declare module 'vscode' {
}
export interface NotebookCell {
readonly index: number;
readonly notebook: NotebookDocument;
readonly uri: Uri;
readonly cellKind: CellKind;
@ -1399,27 +1400,16 @@ declare module 'vscode' {
export interface WorkspaceEdit {
replaceNotebookMetadata(uri: Uri, value: NotebookDocumentMetadata): void;
replaceCells(uri: Uri, start: number, end: number, cells: NotebookCellData[], metadata?: WorkspaceEditEntryMetadata): void;
replaceCellOutput(uri: Uri, index: number, outputs: CellOutput[], metadata?: WorkspaceEditEntryMetadata): void;
replaceCellMetadata(uri: Uri, index: number, cellMetadata: NotebookCellMetadata, metadata?: WorkspaceEditEntryMetadata): void;
replaceNotebookCells(uri: Uri, start: number, end: number, cells: NotebookCellData[], metadata?: WorkspaceEditEntryMetadata): void;
replaceNotebookCellOutput(uri: Uri, index: number, outputs: CellOutput[], metadata?: WorkspaceEditEntryMetadata): void;
replaceNotebookCellMetadata(uri: Uri, index: number, cellMetadata: NotebookCellMetadata, metadata?: WorkspaceEditEntryMetadata): void;
}
export interface NotebookEditorEdit {
replaceNotebookMetadata(value: NotebookDocumentMetadata): void;
replaceMetadata(value: NotebookDocumentMetadata): void;
replaceCells(start: number, end: number, cells: NotebookCellData[]): void;
replaceCellOutput(index: number, outputs: CellOutput[]): void;
replaceCellMetadata(index: number, metadata: NotebookCellMetadata): void;
/** @deprecated */
replaceOutput(index: number, outputs: CellOutput[]): void;
/** @deprecated */
replaceMetadata(index: number, metadata: NotebookCellMetadata): void;
/** @deprecated */
insert(index: number, content: string | string[], language: string, type: CellKind, outputs: CellOutput[], metadata: NotebookCellMetadata | undefined): void;
/** @deprecated */
delete(index: number): void;
}
export interface NotebookCellRange {
@ -1503,6 +1493,16 @@ declare module 'vscode' {
*/
asWebviewUri(localResource: Uri): Uri;
/**
* Perform an edit on the notebook associated with this notebook editor.
*
* The given callback-function is invoked with an [edit-builder](#NotebookEditorEdit) which must
* be used to make edits. Note that the edit-builder is only valid while the
* callback executes.
*
* @param callback A function which can create edits using an [edit-builder](#NotebookEditorEdit).
* @return A promise that resolves with a value indicating if the edits could be applied.
*/
edit(callback: (editBuilder: NotebookEditorEdit) => void): Thenable<boolean>;
revealRange(range: NotebookCellRange, revealType?: NotebookEditorRevealType): void;
@ -2040,32 +2040,6 @@ declare module 'vscode' {
//#endregion
//#region Support `scmResourceState` in `when` clauses #86180 https://github.com/microsoft/vscode/issues/86180
export interface SourceControlResourceState {
/**
* Context value of the resource state. This can be used to contribute resource specific actions.
* For example, if a resource is given a context value as `diffable`. When contributing actions to `scm/resourceState/context`
* using `menus` extension point, you can specify context value for key `scmResourceState` in `when` expressions, like `scmResourceState == diffable`.
* ```
* "contributes": {
* "menus": {
* "scm/resourceState/context": [
* {
* "command": "extension.diff",
* "when": "scmResourceState == diffable"
* }
* ]
* }
* }
* ```
* This will show action `extension.diff` only for resources with `contextValue` is `diffable`.
*/
readonly contextValue?: string;
}
//#endregion
//#region https://github.com/microsoft/vscode/issues/104436
export enum ExtensionRuntime {

View file

@ -29,8 +29,8 @@ import { CustomDocumentBackupData } from 'vs/workbench/contrib/customEditor/brow
import { ICustomEditorModel, ICustomEditorService } from 'vs/workbench/contrib/customEditor/common/customEditor';
import { CustomTextEditorModel } from 'vs/workbench/contrib/customEditor/common/customTextEditorModel';
import { WebviewExtensionDescription } from 'vs/workbench/contrib/webview/browser/webview';
import { WebviewInput } from 'vs/workbench/contrib/webview/browser/webviewEditorInput';
import { IWebviewWorkbenchService } from 'vs/workbench/contrib/webview/browser/webviewWorkbenchService';
import { WebviewInput } from 'vs/workbench/contrib/webviewPanel/browser/webviewEditorInput';
import { IWebviewWorkbenchService } from 'vs/workbench/contrib/webviewPanel/browser/webviewWorkbenchService';
import { IBackupFileService } from 'vs/workbench/services/backup/common/backup';
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';

View file

@ -162,7 +162,7 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
return false;
}
this._notebookService.transformEditsOutputs(textModel, cellEdits);
return textModel.applyEdit(modelVersionId, cellEdits, true, undefined, () => undefined);
return textModel.applyEdits(modelVersionId, cellEdits, true, undefined, () => undefined);
}
private _isDeltaEmpty(delta: INotebookDocumentsAndEditorsDelta) {
@ -460,7 +460,7 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
this._notebookService.transformEditsOutputs(mainthreadTextModel, edits);
await new Promise(resolve => {
DOM.scheduleAtNextAnimationFrame(() => {
const ret = mainthreadTextModel!.applyEdit(mainthreadTextModel!.versionId, edits, true, undefined, () => undefined);
const ret = mainthreadTextModel!.applyEdits(mainthreadTextModel!.versionId, edits, true, undefined, () => undefined);
resolve(ret);
});
});
@ -577,7 +577,7 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
return;
}
textModel.applyEdit(textModel.versionId, [
textModel.applyEdits(textModel.versionId, [
{
editType: CellEditType.OutputsSplice,
index: textModel.cells.indexOf(cell),
@ -614,7 +614,7 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
const textModel = this._notebookService.getNotebookTextModel(URI.from(resource));
if (textModel) {
textModel.applyEdit(textModel.versionId, [
textModel.applyEdits(textModel.versionId, [
{
editType: CellEditType.Unknown
}

View file

@ -5,7 +5,6 @@
import { URI, UriComponents } from 'vs/base/common/uri';
import { Event, Emitter } from 'vs/base/common/event';
import { assign } from 'vs/base/common/objects';
import { IDisposable, DisposableStore, combinedDisposable } from 'vs/base/common/lifecycle';
import { ISCMService, ISCMRepository, ISCMProvider, ISCMResource, ISCMResourceGroup, ISCMResourceDecorations, IInputValidation } from 'vs/workbench/contrib/scm/common/scm';
import { ExtHostContext, MainThreadSCMShape, ExtHostSCMShape, SCMProviderFeatures, SCMRawResourceSplices, SCMGroupFeatures, MainContext, IExtHostContext } from '../common/extHost.protocol';
@ -49,7 +48,7 @@ class MainThreadSCMResourceGroup implements ISCMResourceGroup {
}
$updateGroup(features: SCMGroupFeatures): void {
this.features = assign(this.features, features);
this.features = { ...this.features, ...features };
this._onDidChange.fire();
}
@ -139,7 +138,7 @@ class MainThreadSCMProvider implements ISCMProvider {
) { }
$updateSourceControl(features: SCMProviderFeatures): void {
this.features = assign(this.features, features);
this.features = { ...this.features, ...features };
this._onDidChange.fire();
if (typeof features.commitTemplate !== 'undefined') {

View file

@ -13,8 +13,8 @@ import { editorGroupToViewColumn, EditorViewColumn, viewColumnToEditorGroup } fr
import { IEditorInput } from 'vs/workbench/common/editor';
import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput';
import { WebviewIcons } from 'vs/workbench/contrib/webview/browser/webview';
import { WebviewInput } from 'vs/workbench/contrib/webview/browser/webviewEditorInput';
import { ICreateWebViewShowOptions, IWebviewWorkbenchService, WebviewInputOptions } from 'vs/workbench/contrib/webview/browser/webviewWorkbenchService';
import { WebviewInput } from 'vs/workbench/contrib/webviewPanel/browser/webviewEditorInput';
import { ICreateWebViewShowOptions, IWebviewWorkbenchService, WebviewInputOptions } from 'vs/workbench/contrib/webviewPanel/browser/webviewWorkbenchService';
import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';

View file

@ -15,7 +15,7 @@ import { IOpenerService } from 'vs/platform/opener/common/opener';
import { IProductService } from 'vs/platform/product/common/productService';
import * as extHostProtocol from 'vs/workbench/api/common/extHost.protocol';
import { Webview, WebviewExtensionDescription, WebviewOverlay } from 'vs/workbench/contrib/webview/browser/webview';
import { WebviewInputOptions } from 'vs/workbench/contrib/webview/browser/webviewWorkbenchService';
import { WebviewInputOptions } from 'vs/workbench/contrib/webviewPanel/browser/webviewWorkbenchService';
export class MainThreadWebviews extends Disposable implements extHostProtocol.MainThreadWebviewsShape {

View file

@ -1032,7 +1032,7 @@ export class ExtHostVariableResolverService extends AbstractVariableResolverServ
}
return undefined;
}
}, env, !editorService);
}, undefined, env, !editorService);
}
}

View file

@ -78,7 +78,7 @@ export class DiagnosticCollection implements vscode.DiagnosticCollection {
let lastUri: vscode.Uri | undefined;
// ensure stable-sort
mergeSort(first, DiagnosticCollection._compareIndexedTuplesByUri);
first = mergeSort([...first], DiagnosticCollection._compareIndexedTuplesByUri);
for (const tuple of first) {
const [uri, diagnostics] = tuple;
@ -88,17 +88,17 @@ export class DiagnosticCollection implements vscode.DiagnosticCollection {
}
lastUri = uri;
toSync.push(uri);
this._data.set(uri.toString(), []);
this._data.set(uri, []);
}
if (!diagnostics) {
// [Uri, undefined] means clear this
const currentDiagnostics = this._data.get(uri.toString());
const currentDiagnostics = this._data.get(uri);
if (currentDiagnostics) {
currentDiagnostics.length = 0;
}
} else {
const currentDiagnostics = this._data.get(uri.toString());
const currentDiagnostics = this._data.get(uri);
if (currentDiagnostics) {
currentDiagnostics.push(...diagnostics);
}
@ -198,7 +198,7 @@ export class DiagnosticCollection implements vscode.DiagnosticCollection {
}
}
private static _compareIndexedTuplesByUri(a: [vscode.Uri, vscode.Diagnostic[]], b: [vscode.Uri, vscode.Diagnostic[]]): number {
private static _compareIndexedTuplesByUri(a: [vscode.Uri, readonly vscode.Diagnostic[]], b: [vscode.Uri, readonly vscode.Diagnostic[]]): number {
if (a[0].toString() < b[0].toString()) {
return -1;
} else if (a[0].toString() > b[0].toString()) {

View file

@ -115,6 +115,7 @@ export class ExtHostCell extends Disposable {
const that = this;
const document = this._extHostDocument.getDocument(this.uri)!.document;
this._cell = Object.freeze({
get index() { return that._notebook.getCellIndex(that); },
notebook: that._notebook.notebookDocument,
uri: that.uri,
cellKind: this._cellData.cellKind,
@ -487,6 +488,9 @@ export class ExtHostNotebookDocument extends Disposable {
return this._cells.find(cell => cell.handle === cellHandle);
}
getCellIndex(cell: ExtHostCell): number {
return this._cells.indexOf(cell);
}
addEdit(item: vscode.NotebookDocumentEditEvent): number {
return this._edits.add([item]);

View file

@ -6,7 +6,7 @@
import { readonly } from 'vs/base/common/errors';
import { Emitter, Event } from 'vs/base/common/event';
import { Disposable } from 'vs/base/common/lifecycle';
import { CellKind, MainThreadNotebookShape } from 'vs/workbench/api/common/extHost.protocol';
import { MainThreadNotebookShape } from 'vs/workbench/api/common/extHost.protocol';
import * as extHostTypes from 'vs/workbench/api/common/extHostTypes';
import { addIdToOutput, CellEditType, ICellEditOperation, ICellReplaceEdit, INotebookEditData, notebookDocumentMetadataDefaults } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import * as vscode from 'vscode';
@ -37,7 +37,7 @@ class NotebookEditorCellEditBuilder implements vscode.NotebookEditorEdit {
}
}
replaceNotebookMetadata(value: vscode.NotebookDocumentMetadata): void {
replaceMetadata(value: vscode.NotebookDocumentMetadata): void {
this._throwIfFinalized();
this._collectedEdits.push({
editType: CellEditType.DocumentMetadata,
@ -54,12 +54,6 @@ class NotebookEditorCellEditBuilder implements vscode.NotebookEditorEdit {
});
}
replaceMetadata(index: number, metadata: vscode.NotebookCellMetadata): void {
console.warn('DEPRECATED use "replaceCellMetadata" instead');
this.replaceCellMetadata(index, metadata);
}
replaceCellOutput(index: number, outputs: vscode.CellOutput[]): void {
this._throwIfFinalized();
this._collectedEdits.push({
@ -69,14 +63,11 @@ class NotebookEditorCellEditBuilder implements vscode.NotebookEditorEdit {
});
}
replaceOutput(index: number, outputs: vscode.CellOutput[]): void {
console.warn('DEPRECATED use "replaceCellOutput" instead');
this.replaceCellOutput(index, outputs);
}
replaceCells(from: number, to: number, cells: vscode.NotebookCellData[]): void {
this._throwIfFinalized();
if (from === to && cells.length === 0) {
return;
}
this._collectedEdits.push({
editType: CellEditType.Replace,
index: from,
@ -89,22 +80,6 @@ class NotebookEditorCellEditBuilder implements vscode.NotebookEditorEdit {
})
});
}
insert(index: number, content: string | string[], language: string, type: CellKind, outputs: vscode.CellOutput[], metadata: vscode.NotebookCellMetadata | undefined): void {
this._throwIfFinalized();
this.replaceCells(index, index, [{
language,
outputs,
metadata,
cellKind: type,
source: Array.isArray(content) ? content.join('\n') : content,
}]);
}
delete(index: number): void {
this._throwIfFinalized();
this.replaceCells(index, 1, []);
}
}
export class ExtHostNotebookEditor extends Disposable implements vscode.NotebookEditor {

View file

@ -636,15 +636,17 @@ export class WorkspaceEdit implements vscode.WorkspaceEdit {
this._edits.push({ _type: FileEditType.Cell, metadata, uri, notebookMetadata: value });
}
replaceCells(uri: URI, start: number, end: number, cells: vscode.NotebookCellData[], metadata?: vscode.WorkspaceEditEntryMetadata): void {
this._edits.push({ _type: FileEditType.Cell, metadata, uri, edit: { editType: CellEditType.Replace, index: start, count: end - start, cells: cells.map(cell => ({ ...cell, outputs: cell.outputs.map(output => addIdToOutput(output)) })) } });
replaceNotebookCells(uri: URI, start: number, end: number, cells: vscode.NotebookCellData[], metadata?: vscode.WorkspaceEditEntryMetadata): void {
if (start !== end || cells.length > 0) {
this._edits.push({ _type: FileEditType.Cell, metadata, uri, edit: { editType: CellEditType.Replace, index: start, count: end - start, cells: cells.map(cell => ({ ...cell, outputs: cell.outputs.map(output => addIdToOutput(output)) })) } });
}
}
replaceCellOutput(uri: URI, index: number, outputs: vscode.CellOutput[], metadata?: vscode.WorkspaceEditEntryMetadata): void {
replaceNotebookCellOutput(uri: URI, index: number, outputs: vscode.CellOutput[], metadata?: vscode.WorkspaceEditEntryMetadata): void {
this._edits.push({ _type: FileEditType.Cell, metadata, uri, edit: { editType: CellEditType.Output, index, outputs: outputs.map(output => addIdToOutput(output)) } });
}
replaceCellMetadata(uri: URI, index: number, cellMetadata: vscode.NotebookCellMetadata, metadata?: vscode.WorkspaceEditEntryMetadata): void {
replaceNotebookCellMetadata(uri: URI, index: number, cellMetadata: vscode.NotebookCellMetadata, metadata?: vscode.WorkspaceEditEntryMetadata): void {
this._edits.push({ _type: FileEditType.Cell, metadata, uri, edit: { editType: CellEditType.Metadata, index, metadata: cellMetadata } });
}

View file

@ -368,7 +368,7 @@ namespace schema {
};
export const submenusContribution: IJSONSchema = {
description: localize('vscode.extension.contributes.submenus', "(Proposed API) Contributes submenu items to the editor"),
description: localize('vscode.extension.contributes.submenus', "Contributes submenu items to the editor"),
type: 'array',
items: submenu
};
@ -585,11 +585,6 @@ submenusExtensionPoint.setHandler(extensions => {
return;
}
if (!extension.description.enableProposedApi) {
collector.error(localize('submenu.proposedAPI.invalid', "Submenus are proposed API and are only available when running out of dev or with the following command line switch: --enable-proposed-api {0}", extension.description.identifier.value));
return;
}
let absoluteIcon: { dark: URI; light?: URI; } | ThemeIcon | undefined;
if (entry.value.icon) {
if (typeof entry.value.icon === 'string') {
@ -638,7 +633,6 @@ menusExtensionPoint.setHandler(extensions => {
}
let menu = _apiMenusByKey.get(entry.key);
let isSubmenu = false;
if (!menu) {
const submenu = _submenus.get(entry.key);
@ -649,7 +643,6 @@ menusExtensionPoint.setHandler(extensions => {
id: submenu.id,
description: ''
};
isSubmenu = true;
}
}
@ -663,11 +656,6 @@ menusExtensionPoint.setHandler(extensions => {
return;
}
if (isSubmenu && !extension.description.enableProposedApi) {
collector.error(localize('proposedAPI.invalid.submenu', "{0} is a submenu identifier and is only available when running out of dev or with the following command line switch: --enable-proposed-api {1}", entry.key, extension.description.identifier.value));
return;
}
for (const menuItem of entry.value) {
let item: IMenuItem | ISubmenuItem;
@ -688,13 +676,8 @@ menusExtensionPoint.setHandler(extensions => {
item = { command, alt, group: undefined, order: undefined, when: undefined };
} else {
if (!extension.description.enableProposedApi) {
collector.error(localize('proposedAPI.invalid.submenureference', "Menu item references a submenu which is only available when running out of dev or with the following command line switch: --enable-proposed-api {0}", extension.description.identifier.value));
continue;
}
if (menu.supportsSubmenus === false) {
collector.error(localize('proposedAPI.unsupported.submenureference', "Menu item references a submenu for a menu which doesn't have submenu support."));
collector.error(localize('unsupported.submenureference', "Menu item references a submenu for a menu which doesn't have submenu support."));
continue;
}

View file

@ -11,7 +11,7 @@ import { SyncActionDescriptor, MenuRegistry, MenuId } from 'vs/platform/actions/
import { Registry } from 'vs/platform/registry/common/platform';
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
import { IsFullscreenContext } from 'vs/workbench/browser/contextkeys';
import { IsMacNativeContext, IsDevelopmentContext } from 'vs/platform/contextkey/common/contextkeys';
import { IsMacNativeContext, IsDevelopmentContext, IsWebContext } from 'vs/platform/contextkey/common/contextkeys';
import { IWorkbenchActionRegistry, Extensions } from 'vs/workbench/common/actions';
import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { IQuickInputButton, IQuickInputService, IQuickPickSeparator, IKeyMods, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput';
@ -345,7 +345,7 @@ const viewCategory = nls.localize('view', "View");
registry.registerWorkbenchAction(SyncActionDescriptor.from(ToggleFullScreenAction, { primary: KeyCode.F11, mac: { primary: KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.KEY_F } }), 'View: Toggle Full Screen', viewCategory);
const developerCategory = nls.localize({ key: 'developer', comment: ['A developer on Code itself or someone diagnosing issues in Code'] }, "Developer");
registry.registerWorkbenchAction(SyncActionDescriptor.from(ReloadWindowAction), 'Developer: Reload Window', developerCategory);
registry.registerWorkbenchAction(SyncActionDescriptor.from(ReloadWindowAction), 'Developer: Reload Window', developerCategory, IsWebContext.toNegated());
const helpCategory = nls.localize('help', "Help");
registry.registerWorkbenchAction(SyncActionDescriptor.from(ShowAboutDialogAction), `Help: About`, helpCategory);

View file

@ -13,7 +13,7 @@ import { ICommandService, CommandsRegistry } from 'vs/platform/commands/common/c
import { ADD_ROOT_FOLDER_COMMAND_ID, ADD_ROOT_FOLDER_LABEL, PICK_WORKSPACE_FOLDER_COMMAND_ID } from 'vs/workbench/browser/actions/workspaceCommands';
import { IFileDialogService } from 'vs/platform/dialogs/common/dialogs';
import { MenuRegistry, MenuId, SyncActionDescriptor } from 'vs/platform/actions/common/actions';
import { WorkbenchStateContext, WorkspaceFolderCountContext } from 'vs/workbench/browser/contextkeys';
import { EmptyWorkspaceSupportContext, WorkbenchStateContext, WorkspaceFolderCountContext } from 'vs/workbench/browser/contextkeys';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { Registry } from 'vs/platform/registry/common/platform';
import { IWorkbenchActionRegistry, Extensions } from 'vs/workbench/common/actions';
@ -257,7 +257,7 @@ const workspacesCategory = nls.localize('workspaces', "Workspaces");
registry.registerWorkbenchAction(SyncActionDescriptor.from(AddRootFolderAction), 'Workspaces: Add Folder to Workspace...', workspacesCategory);
registry.registerWorkbenchAction(SyncActionDescriptor.from(GlobalRemoveRootFolderAction), 'Workspaces: Remove Folder from Workspace...', workspacesCategory);
registry.registerWorkbenchAction(SyncActionDescriptor.from(CloseWorkspaceAction, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_F) }), 'Workspaces: Close Workspace', workspacesCategory);
registry.registerWorkbenchAction(SyncActionDescriptor.from(CloseWorkspaceAction, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_F) }), 'Workspaces: Close Workspace', workspacesCategory, EmptyWorkspaceSupportContext);
registry.registerWorkbenchAction(SyncActionDescriptor.from(SaveWorkspaceAsAction), 'Workspaces: Save Workspace As...', workspacesCategory);
registry.registerWorkbenchAction(SyncActionDescriptor.from(DuplicateWorkspaceInNewWindowAction), 'Workspaces: Duplicate Workspace in New Window', workspacesCategory);
@ -301,7 +301,7 @@ MenuRegistry.appendMenuItem(MenuId.MenubarFileMenu, {
precondition: WorkspaceFolderCountContext.notEqualsTo('0')
},
order: 3,
when: WorkbenchStateContext.notEqualsTo('workspace')
when: ContextKeyExpr.and(WorkbenchStateContext.notEqualsTo('workspace'), EmptyWorkspaceSupportContext)
});
MenuRegistry.appendMenuItem(MenuId.MenubarFileMenu, {
@ -311,5 +311,5 @@ MenuRegistry.appendMenuItem(MenuId.MenubarFileMenu, {
title: nls.localize({ key: 'miCloseWorkspace', comment: ['&& denotes a mnemonic'] }, "Close &&Workspace")
},
order: 3,
when: ContextKeyExpr.and(WorkbenchStateContext.isEqualTo('workspace'))
when: ContextKeyExpr.and(WorkbenchStateContext.isEqualTo('workspace'), EmptyWorkspaceSupportContext)
});

View file

@ -20,9 +20,11 @@ import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
import { PanelPositionContext } from 'vs/workbench/common/panel';
import { getRemoteName } from 'vs/platform/remote/common/remoteHosts';
import { IWorkingCopyService } from 'vs/workbench/services/workingCopy/common/workingCopyService';
import { isNative } from 'vs/base/common/platform';
export const WorkbenchStateContext = new RawContextKey<string>('workbenchState', undefined);
export const WorkspaceFolderCountContext = new RawContextKey<number>('workspaceFolderCount', 0);
export const EmptyWorkspaceSupportContext = new RawContextKey<boolean>('emptyWorkspaceSupport', true);
export const DirtyWorkingCopiesContext = new RawContextKey<boolean>('dirtyWorkingCopies', false);
@ -51,6 +53,7 @@ export class WorkbenchContextKeysHandler extends Disposable {
private workbenchStateContext: IContextKey<string>;
private workspaceFolderCountContext: IContextKey<number>;
private emptyWorkspaceSupportContext: IContextKey<boolean>;
private inZenModeContext: IContextKey<boolean>;
private isFullscreenContext: IContextKey<boolean>;
@ -112,6 +115,12 @@ export class WorkbenchContextKeysHandler extends Disposable {
this.workspaceFolderCountContext = WorkspaceFolderCountContext.bindTo(this.contextKeyService);
this.updateWorkspaceFolderCountContextKey();
// Empty workspace support: empty workspaces require a default "local" file
// system to operate with. We always have one when running natively or when
// we have a remote connection.
this.emptyWorkspaceSupportContext = EmptyWorkspaceSupportContext.bindTo(this.contextKeyService);
this.emptyWorkspaceSupportContext.set(isNative || typeof this.environmentService.configuration.remoteAuthority === 'string');
// Editor Layout
this.splitEditorsVerticallyContext = SplitEditorsVertically.bindTo(this.contextKeyService);
this.updateSplitEditorsVerticallyContext();

View file

@ -13,7 +13,7 @@ import { IBadge, NumberBadge } from 'vs/workbench/services/activity/common/activ
import { IWorkbenchLayoutService, Parts } from 'vs/workbench/services/layout/browser/layoutService';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IDisposable, toDisposable, DisposableStore, Disposable } from 'vs/base/common/lifecycle';
import { ToggleActivityBarVisibilityAction, ToggleMenuBarAction } from 'vs/workbench/browser/actions/layoutActions';
import { ToggleActivityBarVisibilityAction, ToggleMenuBarAction, ToggleSidebarPositionAction } from 'vs/workbench/browser/actions/layoutActions';
import { IThemeService, IColorTheme } from 'vs/platform/theme/common/themeService';
import { ACTIVITY_BAR_BACKGROUND, ACTIVITY_BAR_BORDER, ACTIVITY_BAR_FOREGROUND, ACTIVITY_BAR_ACTIVE_BORDER, ACTIVITY_BAR_BADGE_BACKGROUND, ACTIVITY_BAR_BADGE_FOREGROUND, ACTIVITY_BAR_INACTIVE_FOREGROUND, ACTIVITY_BAR_ACTIVE_BACKGROUND, ACTIVITY_BAR_DRAG_AND_DROP_BORDER } from 'vs/workbench/common/theme';
import { contrastBorder } from 'vs/platform/theme/common/colorRegistry';
@ -179,6 +179,7 @@ export class ActivitybarPart extends Part implements IActivityBarService {
actions.push(toggleAccountsVisibilityAction);
actions.push(new Separator());
actions.push(this.instantiationService.createInstance(ToggleSidebarPositionAction, ToggleSidebarPositionAction.ID, ToggleSidebarPositionAction.getLabel(this.layoutService)));
actions.push(new Action(
ToggleActivityBarVisibilityAction.ID,
nls.localize('hideActivitBar', "Hide Activity Bar"),

View file

@ -365,7 +365,7 @@ export abstract class ViewPane extends Pane implements IView {
}
const calculatedTitle = this.calculateTitle(title);
this.titleContainer = append(container, $('h3.title', undefined, calculatedTitle));
this.titleContainer = append(container, $('h3.title', { title: calculatedTitle }, calculatedTitle));
if (this._titleDescription) {
this.setTitleDescription(this._titleDescription);
@ -379,6 +379,7 @@ export abstract class ViewPane extends Pane implements IView {
const calculatedTitle = this.calculateTitle(title);
if (this.titleContainer) {
this.titleContainer.textContent = calculatedTitle;
this.titleContainer.setAttribute('title', calculatedTitle);
}
if (this.iconContainer) {
@ -393,9 +394,10 @@ export abstract class ViewPane extends Pane implements IView {
private setTitleDescription(description: string | undefined) {
if (this.titleDescriptionContainer) {
this.titleDescriptionContainer.textContent = description ?? '';
this.titleDescriptionContainer.setAttribute('title', description ?? '');
}
else if (description && this.titleContainer) {
this.titleDescriptionContainer = after(this.titleContainer, $('span.description', undefined, description));
this.titleDescriptionContainer = after(this.titleContainer, $('span.description', { title: description }, description));
}
}

View file

@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { mark } from 'vs/base/common/performance';
import { domContentLoaded, addDisposableListener, EventType, EventHelper } from 'vs/base/browser/dom';
import { domContentLoaded, addDisposableListener, EventType, EventHelper, detectFullscreen, addDisposableThrottledListener } from 'vs/base/browser/dom';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { ILogService, ConsoleLogService, MultiplexLogService } from 'vs/platform/log/common/log';
import { ConsoleLogInAutomationService } from 'vs/platform/log/browser/log';
@ -25,8 +25,8 @@ import { Schemas } from 'vs/base/common/network';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { onUnexpectedError } from 'vs/base/common/errors';
import * as browser from 'vs/base/browser/browser';
import * as platform from 'vs/base/common/platform';
import { setFullscreen } from 'vs/base/browser/browser';
import { isIOS, isMacintosh } from 'vs/base/common/platform';
import { URI } from 'vs/base/common/uri';
import { IWorkspaceInitializationPayload } from 'vs/platform/workspaces/common/workspaces';
import { WorkspaceService } from 'vs/workbench/services/configuration/browser/configurationService';
@ -58,6 +58,14 @@ class BrowserMain extends Disposable {
private readonly configuration: IWorkbenchConstructionOptions
) {
super();
this.init();
}
private init(): void {
// Browser config
setFullscreen(!!detectFullscreen());
}
async open(): Promise<IWorkbench> {
@ -99,7 +107,7 @@ class BrowserMain extends Disposable {
private registerListeners(workbench: Workbench, storageService: BrowserStorageService): void {
// Layout
const viewport = platform.isIOS && (<any>window).visualViewport ? (<any>window).visualViewport /** Visual viewport */ : window /** Layout viewport */;
const viewport = isIOS && window.visualViewport ? window.visualViewport /** Visual viewport */ : window /** Layout viewport */;
this._register(addDisposableListener(viewport, EventType.RESIZE, () => workbench.layout()));
// Prevent the back/forward gestures in macOS
@ -123,16 +131,15 @@ class BrowserMain extends Disposable {
}));
this._register(workbench.onShutdown(() => this.dispose()));
// Fullscreen
// Fullscreen (Browser)
[EventType.FULLSCREEN_CHANGE, EventType.WK_FULLSCREEN_CHANGE].forEach(event => {
this._register(addDisposableListener(document, event, () => {
if (document.fullscreenElement || (<any>document).webkitFullscreenElement || (<any>document).webkitIsFullScreen) {
browser.setFullscreen(true);
} else {
browser.setFullscreen(false);
}
}));
this._register(addDisposableListener(document, event, () => setFullscreen(!!detectFullscreen())));
});
// Fullscreen (Native)
this._register(addDisposableThrottledListener(viewport, EventType.RESIZE, () => {
setFullscreen(!!detectFullscreen());
}, undefined, isMacintosh ? 2000 /* adjust for macOS animation */ : 800 /* can be throttled */));
}
private async initServices(): Promise<{ serviceCollection: ServiceCollection, logService: ILogService, storageService: BrowserStorageService }> {
@ -214,7 +221,7 @@ class BrowserMain extends Disposable {
// Initialize required resources - settings & global state
await userDataInitializationService.initializeRequiredResources();
// Important Reload only local user configuration after initializing
// Important: Reload only local user configuration after initializing
// Reloading complete configuraiton blocks workbench until remote configuration is loaded.
await configurationService.reloadLocalUserConfiguration();
mark('didInitRequiredUserData');

View file

@ -51,7 +51,7 @@ export class BulkCellEdits {
// apply edits
const edits = group.map(entry => entry.cellEdit);
this._notebookService.transformEditsOutputs(ref.object.notebook, edits);
ref.object.notebook.applyEdit(ref.object.notebook.versionId, edits, true, undefined, () => undefined);
ref.object.notebook.applyEdits(ref.object.notebook.versionId, edits, true, undefined, () => undefined);
ref.dispose();
this._progress.report(undefined);

View file

@ -3,8 +3,6 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as os from 'os';
import * as nls from 'vs/nls';
import { Range } from 'vs/editor/common/core/range';
import { Action } from 'vs/base/common/actions';
@ -22,6 +20,8 @@ import { ITextModel } from 'vs/editor/common/model';
import { Constants } from 'vs/base/common/uint';
import { IHostService } from 'vs/workbench/services/host/browser/host';
import { join } from 'vs/base/common/path';
import { INativeWorkbenchEnvironmentService } from 'vs/workbench/services/environment/electron-sandbox/environmentService';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
class StartDebugTextMate extends Action {
@ -37,7 +37,8 @@ class StartDebugTextMate extends Action {
@IModelService private readonly _modelService: IModelService,
@IEditorService private readonly _editorService: IEditorService,
@ICodeEditorService private readonly _codeEditorService: ICodeEditorService,
@IHostService private readonly _hostService: IHostService
@IHostService private readonly _hostService: IHostService,
@IWorkbenchEnvironmentService private readonly _environmentService: INativeWorkbenchEnvironmentService
) {
super(id, label);
}
@ -59,7 +60,7 @@ class StartDebugTextMate extends Action {
}
public async run(): Promise<any> {
const pathInTemp = join(os.tmpdir(), `vcode-tm-log-${generateUuid()}.txt`);
const pathInTemp = join(this._environmentService.tmpDir.fsPath, `vcode-tm-log-${generateUuid()}.txt`);
const logger = createRotatingLogger(`tm-log`, pathInTemp, 1024 * 1024 * 30, 1);
const model = this._getOrCreateModel();
const append = (str: string) => {

View file

@ -13,7 +13,7 @@ import { Extensions as WorkbenchExtensions, IWorkbenchContributionsRegistry } fr
import { Extensions as EditorInputExtensions, IEditorInputFactoryRegistry } from 'vs/workbench/common/editor';
import { CustomEditorInputFactory } from 'vs/workbench/contrib/customEditor/browser/customEditorInputFactory';
import { ICustomEditorService } from 'vs/workbench/contrib/customEditor/common/customEditor';
import { WebviewEditor } from 'vs/workbench/contrib/webview/browser/webviewEditor';
import { WebviewEditor } from 'vs/workbench/contrib/webviewPanel/browser/webviewEditor';
import { CustomEditorInput } from './customEditorInput';
import { CustomEditorContribution, CustomEditorService } from './customEditors';

View file

@ -18,7 +18,7 @@ import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo';
import { GroupIdentifier, IEditorInput, IRevertOptions, ISaveOptions, Verbosity } from 'vs/workbench/common/editor';
import { ICustomEditorModel, ICustomEditorService } from 'vs/workbench/contrib/customEditor/common/customEditor';
import { IWebviewService, WebviewOverlay } from 'vs/workbench/contrib/webview/browser/webview';
import { IWebviewWorkbenchService, LazilyResolvedWebviewEditorInput } from 'vs/workbench/contrib/webview/browser/webviewWorkbenchService';
import { IWebviewWorkbenchService, LazilyResolvedWebviewEditorInput } from 'vs/workbench/contrib/webviewPanel/browser/webviewWorkbenchService';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { AutoSaveMode, IFilesConfigurationService } from 'vs/workbench/services/filesConfiguration/common/filesConfigurationService';

View file

@ -9,8 +9,8 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
import { IEditorInput } from 'vs/workbench/common/editor';
import { CustomEditorInput } from 'vs/workbench/contrib/customEditor/browser/customEditorInput';
import { IWebviewService, WebviewExtensionDescription, WebviewContentPurpose } from 'vs/workbench/contrib/webview/browser/webview';
import { reviveWebviewExtensionDescription, SerializedWebview, WebviewEditorInputFactory, DeserializedWebview } from 'vs/workbench/contrib/webview/browser/webviewEditorInputFactory';
import { IWebviewWorkbenchService, WebviewInputOptions } from 'vs/workbench/contrib/webview/browser/webviewWorkbenchService';
import { reviveWebviewExtensionDescription, SerializedWebview, WebviewEditorInputFactory, DeserializedWebview } from 'vs/workbench/contrib/webviewPanel/browser/webviewEditorInputFactory';
import { IWebviewWorkbenchService, WebviewInputOptions } from 'vs/workbench/contrib/webviewPanel/browser/webviewWorkbenchService';
import { IBackupFileService } from 'vs/workbench/services/backup/common/backup';
export interface CustomDocumentBackupData {

View file

@ -95,8 +95,12 @@ export function prepareCommand(shell: string, args: string[], cwd?: string, env?
}
let quote: (s: string) => string;
// cancel the current input (to avoid executing the command accidentally)
let command = '\u0003'; // Control-C
// begin command with a space to avoid polluting shell history
let command = ' ';
command += ' ';
switch (shellType) {

View file

@ -353,8 +353,6 @@ export class ExtensionsViewPaneContainer extends ViewPaneContainer implements IE
@IInstantiationService instantiationService: IInstantiationService,
@IEditorGroupsService private readonly editorGroupService: IEditorGroupsService,
@IExtensionManagementService private readonly extensionManagementService: IExtensionManagementService,
@IExtensionManagementServerService private readonly extensionManagementServerService: IExtensionManagementServerService,
@IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService,
@IExtensionGalleryService private readonly extensionGalleryService: IExtensionGalleryService,
@INotificationService private readonly notificationService: INotificationService,
@IViewletService private readonly viewletService: IViewletService,
@ -534,9 +532,6 @@ export class ExtensionsViewPaneContainer extends ViewPaneContainer implements IE
new SubmenuAction('workbench.extensions.action.filterExtensionsByCategory', localize('filter by category', "Category"), EXTENSION_CATEGORIES.map(category => this.instantiationService.createInstance(SearchCategoryAction, `extensions.actions.searchByCategory.${category}`, category, category))),
new Separator(),
];
if (this.extensionManagementServerService.webExtensionManagementServer || !this.environmentService.isBuilt) {
galleryFilterActions.splice(4, 0, this.instantiationService.createInstance(PredefinedExtensionFilterAction, 'extensions.filter.web', localize('web filter', "Web"), '@web'));
}
filterActions.splice(0, 0, ...galleryFilterActions);
filterActions.push(...[
new Separator(),

View file

@ -1163,7 +1163,7 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension
return changed;
}
private _activityCallBack: (() => void) | null = null;
private _activityCallBack: ((value: void) => void) | null = null;
private updateActivity(): void {
if ((this.localExtensions && this.localExtensions.local.some(e => e.state === ExtensionState.Installing || e.state === ExtensionState.Uninstalling))
|| (this.remoteExtensions && this.remoteExtensions.local.some(e => e.state === ExtensionState.Installing || e.state === ExtensionState.Uninstalling))

View file

@ -37,7 +37,7 @@ import { randomPort } from 'vs/base/node/ports';
import { IContextKeyService, RawContextKey, IContextKey } from 'vs/platform/contextkey/common/contextkey';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { ILabelService } from 'vs/platform/label/common/label';
import { renderCodiconsAsElement } from 'vs/base/browser/codicons';
import { renderCodicons } from 'vs/base/browser/codicons';
import { ExtensionIdentifier, ExtensionType, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
import { Schemas } from 'vs/base/common/network';
import { SlowExtensionAction } from 'vs/workbench/contrib/extensions/electron-browser/extensionsSlowActions';
@ -408,28 +408,28 @@ export class RuntimeExtensionsEditor extends EditorPane {
clearNode(data.msgContainer);
if (this._extensionHostProfileService.getUnresponsiveProfile(element.description.identifier)) {
const el = $('span', undefined, ...renderCodiconsAsElement(` $(alert) Unresponsive`));
const el = $('span', undefined, ...renderCodicons(` $(alert) Unresponsive`));
el.title = nls.localize('unresponsive.title', "Extension has caused the extension host to freeze.");
data.msgContainer.appendChild(el);
}
if (isNonEmptyArray(element.status.runtimeErrors)) {
const el = $('span', undefined, ...renderCodiconsAsElement(`$(bug) ${nls.localize('errors', "{0} uncaught errors", element.status.runtimeErrors.length)}`));
const el = $('span', undefined, ...renderCodicons(`$(bug) ${nls.localize('errors', "{0} uncaught errors", element.status.runtimeErrors.length)}`));
data.msgContainer.appendChild(el);
}
if (element.status.messages && element.status.messages.length > 0) {
const el = $('span', undefined, ...renderCodiconsAsElement(`$(alert) ${element.status.messages[0].message}`));
const el = $('span', undefined, ...renderCodicons(`$(alert) ${element.status.messages[0].message}`));
data.msgContainer.appendChild(el);
}
if (element.description.extensionLocation.scheme !== 'file') {
const el = $('span', undefined, ...renderCodiconsAsElement(`$(remote) ${element.description.extensionLocation.authority}`));
const el = $('span', undefined, ...renderCodicons(`$(remote) ${element.description.extensionLocation.authority}`));
data.msgContainer.appendChild(el);
const hostLabel = this._labelService.getHostLabel(Schemas.vscodeRemote, this._environmentService.configuration.remoteAuthority);
if (hostLabel) {
reset(el, ...renderCodiconsAsElement(`$(remote) ${hostLabel}`));
reset(el, ...renderCodicons(`$(remote) ${hostLabel}`));
}
}

View file

@ -50,6 +50,7 @@ import { ExtensionTipsService } from 'vs/platform/extensionManagement/node/exten
import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle';
import { TestLifecycleService } from 'vs/workbench/test/browser/workbenchTestServices';
import { DisposableStore } from 'vs/base/common/lifecycle';
import { INativeWorkbenchEnvironmentService } from 'vs/workbench/services/environment/electron-sandbox/environmentService';
let instantiationService: TestInstantiationService;
let installEvent: Emitter<InstallExtensionEvent>,
@ -99,7 +100,7 @@ async function setupTest() {
instantiationService.stub(IExtensionManagementServerService, new class extends ExtensionManagementServerService {
#localExtensionManagementServer: IExtensionManagementServer = { extensionManagementService: instantiationService.get(IExtensionManagementService), label: 'local', id: 'vscode-local' };
constructor() {
super(instantiationService.get(ISharedProcessService), instantiationService.get(IRemoteAgentService), instantiationService.get(ILabelService), instantiationService.get(IExtensionGalleryService), instantiationService.get(IProductService), instantiationService.get(IConfigurationService), instantiationService.get(ILogService));
super(instantiationService.get(ISharedProcessService), instantiationService.get(IRemoteAgentService), instantiationService.get(ILabelService), instantiationService.get(IExtensionGalleryService), instantiationService.get(IProductService), instantiationService.get(IConfigurationService), instantiationService.get(ILogService), instantiationService.get(IWorkbenchEnvironmentService) as INativeWorkbenchEnvironmentService);
}
get localExtensionManagementServer(): IExtensionManagementServer { return this.#localExtensionManagementServer; }
set localExtensionManagementServer(server: IExtensionManagementServer) { }

View file

@ -45,6 +45,8 @@ import { IMenuService } from 'vs/platform/actions/common/actions';
import { TestContextService } from 'vs/workbench/test/common/workbenchTestServices';
import { IViewDescriptorService, ViewContainerLocation } from 'vs/workbench/common/views';
import { IProductService } from 'vs/platform/product/common/productService';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
import { INativeWorkbenchEnvironmentService } from 'vs/workbench/services/environment/electron-sandbox/environmentService';
suite('ExtensionsListView Tests', () => {
@ -104,7 +106,7 @@ suite('ExtensionsListView Tests', () => {
instantiationService.stub(IExtensionManagementServerService, new class extends ExtensionManagementServerService {
#localExtensionManagementServer: IExtensionManagementServer = { extensionManagementService: instantiationService.get(IExtensionManagementService), label: 'local', id: 'vscode-local' };
constructor() {
super(instantiationService.get(ISharedProcessService), instantiationService.get(IRemoteAgentService), instantiationService.get(ILabelService), instantiationService.get(IExtensionGalleryService), instantiationService.get(IProductService), instantiationService.get(IConfigurationService), instantiationService.get(ILogService));
super(instantiationService.get(ISharedProcessService), instantiationService.get(IRemoteAgentService), instantiationService.get(ILabelService), instantiationService.get(IExtensionGalleryService), instantiationService.get(IProductService), instantiationService.get(IConfigurationService), instantiationService.get(ILogService), instantiationService.get(IWorkbenchEnvironmentService) as INativeWorkbenchEnvironmentService);
}
get localExtensionManagementServer(): IExtensionManagementServer { return this.#localExtensionManagementServer; }
set localExtensionManagementServer(server: IExtensionManagementServer) { }

View file

@ -22,7 +22,7 @@ import { AutoSaveAfterShortDelayContext } from 'vs/workbench/services/filesConfi
import { ResourceContextKey } from 'vs/workbench/common/resources';
import { WorkbenchListDoubleSelection } from 'vs/platform/list/browser/listService';
import { Schemas } from 'vs/base/common/network';
import { DirtyWorkingCopiesContext, WorkspaceFolderCountContext } from 'vs/workbench/browser/contextkeys';
import { DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, WorkspaceFolderCountContext } from 'vs/workbench/browser/contextkeys';
import { IsWebContext } from 'vs/platform/contextkey/common/contextkeys';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { OpenFileFolderAction, OpenFileAction, OpenFolderAction, OpenWorkspaceAction } from 'vs/workbench/browser/actions/workspaceActions';
@ -42,7 +42,7 @@ registry.registerWorkbenchAction(SyncActionDescriptor.from(CollapseExplorerView)
registry.registerWorkbenchAction(SyncActionDescriptor.from(RefreshExplorerView), 'File: Refresh Explorer', category.value);
registry.registerWorkbenchAction(SyncActionDescriptor.from(CompareWithClipboardAction, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_C) }), 'File: Compare Active File with Clipboard', category.value);
registry.registerWorkbenchAction(SyncActionDescriptor.from(ToggleAutoSaveAction), 'File: Toggle Auto Save', category.value);
registry.registerWorkbenchAction(SyncActionDescriptor.from(ShowOpenedFileInNewWindow, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_O) }), 'File: Open Active File in New Window', category.value);
registry.registerWorkbenchAction(SyncActionDescriptor.from(ShowOpenedFileInNewWindow, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_O) }), 'File: Open Active File in New Window', category.value, EmptyWorkspaceSupportContext);
const workspacesCategory = nls.localize('workspaces', "Workspaces");
registry.registerWorkbenchAction(SyncActionDescriptor.from(OpenWorkspaceAction), 'Workspaces: Open Workspace...', workspacesCategory);

View file

@ -121,7 +121,7 @@ class DefaultFormatter extends Disposable implements IWorkbenchContribution {
if (silent) {
// don't wait when formatting happens without interaction
// but pick some formatter...
resolve(formatter[0]);
resolve(undefined);
}
});
}

View file

@ -8,10 +8,10 @@ import * as nls from 'vs/nls';
import product from 'vs/platform/product/common/product';
import { SyncActionDescriptor, ICommandAction, MenuRegistry, MenuId } from 'vs/platform/actions/common/actions';
import { IWorkbenchActionRegistry, Extensions } from 'vs/workbench/common/actions';
import { ReportPerformanceIssueUsingReporterAction, OpenProcessExplorer } from 'vs/workbench/contrib/issue/electron-browser/issueActions';
import { ReportPerformanceIssueUsingReporterAction, OpenProcessExplorer } from 'vs/workbench/contrib/issue/electron-sandbox/issueActions';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { IWorkbenchIssueService } from 'vs/workbench/contrib/issue/electron-browser/issue';
import { WorkbenchIssueService } from 'vs/workbench/contrib/issue/electron-browser/issueService';
import { IWorkbenchIssueService } from 'vs/workbench/contrib/issue/electron-sandbox/issue';
import { WorkbenchIssueService } from 'vs/workbench/contrib/issue/electron-sandbox/issueService';
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
import { IssueReporterData } from 'vs/platform/issue/common/issue';
import { IIssueService } from 'vs/platform/issue/electron-sandbox/issue';

View file

@ -6,7 +6,7 @@
import { Action } from 'vs/base/common/actions';
import * as nls from 'vs/nls';
import { IssueType } from 'vs/platform/issue/common/issue';
import { IWorkbenchIssueService } from 'vs/workbench/contrib/issue/electron-browser/issue';
import { IWorkbenchIssueService } from 'vs/workbench/contrib/issue/electron-sandbox/issue';
export class OpenProcessExplorer extends Action {
static readonly ID = 'workbench.action.openProcessExplorer';

View file

@ -11,11 +11,11 @@ import { SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme';
import { IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { IWorkbenchExtensionEnablementService } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
import { getZoomLevel } from 'vs/base/browser/browser';
import { IWorkbenchIssueService } from 'vs/workbench/contrib/issue/electron-browser/issue';
import { IWorkbenchIssueService } from 'vs/workbench/contrib/issue/electron-sandbox/issue';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
import { INativeWorkbenchEnvironmentService } from 'vs/workbench/services/environment/electron-sandbox/environmentService';
import { ExtensionType } from 'vs/platform/extensions/common/extensions';
import { platform } from 'process';
import { platform, PlatformToString } from 'vs/base/common/platform';
import { IProductService } from 'vs/platform/product/common/productService';
export class WorkbenchIssueService implements IWorkbenchIssueService {
@ -71,7 +71,7 @@ export class WorkbenchIssueService implements IWorkbenchIssueService {
hoverForeground: getColor(theme, listHoverForeground),
highlightForeground: getColor(theme, listHighlightForeground),
},
platform,
platform: PlatformToString(platform),
applicationName: this.productService.applicationName
};
return this.issueService.openProcessExplorer(data);

View file

@ -511,27 +511,33 @@ export async function changeCellToKind(kind: CellKind, context: INotebookCellAct
return null;
}
if (!notebookEditor.viewModel) {
return null;
}
const text = cell.getText();
if (!notebookEditor.insertNotebookCell(cell, kind, 'below', text)) {
return null;
}
const idx = notebookEditor.viewModel.getCellIndex(cell);
notebookEditor.viewModel.notebookDocument.applyEdits(notebookEditor.viewModel.notebookDocument.versionId, [
{
editType: CellEditType.Replace,
index: idx,
count: 1,
cells: [{
cellKind: kind,
source: text,
language: language!,
outputs: cell.model.outputs,
metadata: cell.metadata,
}]
}
], true, undefined, () => undefined, true);
const newCell = notebookEditor.viewModel.viewCells[idx];
const idx = notebookEditor.viewModel?.getCellIndex(cell);
if (typeof idx !== 'number') {
return null;
}
const newCell = notebookEditor.viewModel?.viewCells[idx + 1];
if (!newCell) {
return null;
}
if (language) {
newCell.model.language = language;
}
notebookEditor.focusNotebookCell(newCell, cell.editState === CellEditState.Editing ? 'editor' : 'container');
notebookEditor.deleteNotebookCell(cell);
return newCell;
}
@ -1301,10 +1307,10 @@ registerAction2(class extends NotebookCellAction {
return;
}
editor.viewModel.notebookDocument.applyEdit(editor.viewModel.notebookDocument.versionId, [{ editType: CellEditType.Output, index, outputs: [] }], true, undefined, () => undefined);
editor.viewModel.notebookDocument.applyEdits(editor.viewModel.notebookDocument.versionId, [{ editType: CellEditType.Output, index, outputs: [] }], true, undefined, () => undefined);
if (context.cell.metadata && context.cell.metadata?.runState !== NotebookCellRunState.Running) {
context.notebookEditor.viewModel!.notebookDocument.applyEdit(context.notebookEditor.viewModel!.notebookDocument.versionId, [{
context.notebookEditor.viewModel!.notebookDocument.applyEdits(context.notebookEditor.viewModel!.notebookDocument.versionId, [{
editType: CellEditType.Metadata, index, metadata: {
...context.cell.metadata,
runState: NotebookCellRunState.Idle,
@ -1388,11 +1394,11 @@ export class ChangeCellLanguageAction extends NotebookCellAction {
if (newCell) {
context.notebookEditor.focusNotebookCell(newCell, 'editor');
}
} else if (selection.languageId !== 'markdown' && context.cell?.language === 'markdown') {
} else if (selection.languageId !== 'markdown' && context.cell?.cellKind === CellKind.Markdown) {
await changeCellToKind(CellKind.Code, { cell: context.cell, notebookEditor: context.notebookEditor }, selection.languageId);
} else {
const index = context.notebookEditor.viewModel!.notebookDocument.cells.indexOf(context.cell.model);
context.notebookEditor.viewModel!.notebookDocument.applyEdit(
context.notebookEditor.viewModel!.notebookDocument.applyEdits(
context.notebookEditor.viewModel!.notebookDocument.versionId,
[{ editType: CellEditType.CellLanguage, index, language: selection.languageId }],
true, undefined, () => undefined
@ -1443,7 +1449,7 @@ registerAction2(class extends NotebookAction {
return;
}
editor.viewModel.notebookDocument.applyEdit(editor.viewModel.notebookDocument.versionId,
editor.viewModel.notebookDocument.applyEdits(editor.viewModel.notebookDocument.versionId,
editor.viewModel.notebookDocument.cells.map((cell, index) => ({
editType: CellEditType.Output, index, outputs: []
})), true, undefined, () => undefined);
@ -1580,7 +1586,7 @@ abstract class ChangeNotebookCellMetadataAction extends NotebookCellAction {
return;
}
textModel.applyEdit(textModel.versionId, [{ editType: CellEditType.Metadata, index, metadata: { ...context.cell.metadata, ...this.getMetadataDelta() } }], true, undefined, () => undefined);
textModel.applyEdits(textModel.versionId, [{ editType: CellEditType.Metadata, index, metadata: { ...context.cell.metadata, ...this.getMetadataDelta() } }], true, undefined, () => undefined);
}
abstract getMetadataDelta(): NotebookCellMetadata;

View file

@ -12,7 +12,7 @@ import { CellDiffRenderTemplate, CellDiffViewModelLayoutChangeEvent, DIFF_CELL_M
import { EDITOR_BOTTOM_PADDING, EDITOR_TOP_PADDING } from 'vs/workbench/contrib/notebook/browser/constants';
import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget';
import { DiffEditorWidget } from 'vs/editor/browser/widget/diffEditorWidget';
import { renderCodiconsAsElement } from 'vs/base/browser/codicons';
import { renderCodicons } from 'vs/base/browser/codicons';
import { IModelService } from 'vs/editor/common/services/modelService';
import { IModeService } from 'vs/editor/common/services/modeService';
import { format } from 'vs/base/common/jsonFormatter';
@ -194,9 +194,9 @@ class PropertyHeader extends Disposable {
private _updateFoldingIcon() {
if (this.accessor.getFoldingState(this.cell) === PropertyFoldingState.Collapsed) {
DOM.reset(this._foldingIndicator, ...renderCodiconsAsElement('$(chevron-right)'));
DOM.reset(this._foldingIndicator, ...renderCodicons('$(chevron-right)'));
} else {
DOM.reset(this._foldingIndicator, ...renderCodiconsAsElement('$(chevron-down)'));
DOM.reset(this._foldingIndicator, ...renderCodicons('$(chevron-down)'));
}
}
}
@ -473,7 +473,7 @@ abstract class AbstractCellRenderer extends Disposable {
if (newLangauge !== undefined && newLangauge !== this.cell.modified!.language) {
const index = this.notebookEditor.textModel!.cells.indexOf(this.cell.modified!);
this.notebookEditor.textModel!.applyEdit(
this.notebookEditor.textModel!.applyEdits(
this.notebookEditor.textModel!.versionId,
[{ editType: CellEditType.CellLanguage, index, language: newLangauge }],
true,
@ -488,7 +488,7 @@ abstract class AbstractCellRenderer extends Disposable {
return;
}
this.notebookEditor.textModel!.applyEdit(this.notebookEditor.textModel!.versionId, [
this.notebookEditor.textModel!.applyEdits(this.notebookEditor.textModel!.versionId, [
{ editType: CellEditType.Metadata, index, metadata: result }
], true, undefined, () => undefined);
} catch {

View file

@ -290,7 +290,7 @@ export class NotebookContribution extends Disposable implements IWorkbenchContri
private onEditorOpening2(originalInput: IEditorInput, options: IEditorOptions | ITextEditorOptions | undefined, group: IEditorGroup): IOpenEditorOverride | undefined {
let id = typeof options?.override === 'string' ? options.override : undefined;
if (id === undefined && originalInput.isUntitled()) {
if (id === undefined && originalInput.resource?.scheme === Schemas.untitled) {
return undefined;
}

View file

@ -10,7 +10,7 @@ import { IListRenderer, IListVirtualDelegate } from 'vs/base/browser/ui/list/lis
import { ProgressBar } from 'vs/base/browser/ui/progressbar/progressbar';
import { ToolBar } from 'vs/base/browser/ui/toolbar/toolbar';
import { IAction } from 'vs/base/common/actions';
import { renderCodiconsAsElement } from 'vs/base/browser/codicons';
import { renderCodicons } from 'vs/base/browser/codicons';
import { Color } from 'vs/base/common/color';
import { Emitter, Event } from 'vs/base/common/event';
import { Disposable, DisposableStore, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
@ -340,11 +340,11 @@ abstract class AbstractCellRenderer {
}
if (templateData.currentRenderedCell.metadata?.inputCollapsed) {
textModel.applyEdit(textModel.versionId, [
textModel.applyEdits(textModel.versionId, [
{ editType: CellEditType.Metadata, index, metadata: { ...templateData.currentRenderedCell.metadata, inputCollapsed: false } }
], true, undefined, () => undefined);
} else if (templateData.currentRenderedCell.metadata?.outputCollapsed) {
textModel.applyEdit(textModel.versionId, [
textModel.applyEdits(textModel.versionId, [
{ editType: CellEditType.Metadata, index, metadata: { ...templateData.currentRenderedCell.metadata, outputCollapsed: false } }
], true, undefined, () => undefined);
}
@ -352,7 +352,7 @@ abstract class AbstractCellRenderer {
}
protected setupCollapsedPart(container: HTMLElement): { collapsedPart: HTMLElement, expandButton: HTMLElement } {
const collapsedPart = DOM.append(container, $('.cell.cell-collapsed-part', undefined, ...renderCodiconsAsElement('$(unfold)')));
const collapsedPart = DOM.append(container, $('.cell.cell-collapsed-part', undefined, ...renderCodicons('$(unfold)')));
const expandButton = collapsedPart.querySelector('.codicon') as HTMLElement;
const keybinding = this.keybindingService.lookupKeybinding(EXPAND_CELL_CONTENT_COMMAND_ID);
let title = localize('cellExpandButtonLabel', "Expand");
@ -960,11 +960,11 @@ export class RunStateRenderer {
}
if (runState === NotebookCellRunState.Success) {
DOM.reset(this.element, ...renderCodiconsAsElement('$(check)'));
DOM.reset(this.element, ...renderCodicons('$(check)'));
} else if (runState === NotebookCellRunState.Error) {
DOM.reset(this.element, ...renderCodiconsAsElement('$(error)'));
DOM.reset(this.element, ...renderCodicons('$(error)'));
} else if (runState === NotebookCellRunState.Running) {
DOM.reset(this.element, ...renderCodiconsAsElement('$(sync~spin)'));
DOM.reset(this.element, ...renderCodicons('$(sync~spin)'));
this.spinnerTimer = setTimeout(() => {
this.spinnerTimer = undefined;

View file

@ -9,7 +9,7 @@ import { MenuItemAction } from 'vs/platform/actions/common/actions';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { renderCodiconsAsElement } from 'vs/base/browser/codicons';
import { renderCodicons } from 'vs/base/browser/codicons';
export class CodiconActionViewItem extends MenuEntryActionViewItem {
constructor(
@ -22,7 +22,7 @@ export class CodiconActionViewItem extends MenuEntryActionViewItem {
}
updateLabel(): void {
if (this.options.label && this.label) {
DOM.reset(this.label, ...renderCodiconsAsElement(this._commandAction.label ?? ''));
DOM.reset(this.label, ...renderCodicons(this._commandAction.label ?? ''));
}
}
}

View file

@ -6,7 +6,7 @@
import * as DOM from 'vs/base/browser/dom';
import { raceCancellation } from 'vs/base/common/async';
import { CancellationTokenSource } from 'vs/base/common/cancellation';
import { renderCodiconsAsElement } from 'vs/base/browser/codicons';
import { renderCodicons } from 'vs/base/browser/codicons';
import { Disposable, DisposableStore, toDisposable } from 'vs/base/common/lifecycle';
import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget';
import { IEditorOptions } from 'vs/editor/common/config/editorOptions';
@ -315,10 +315,10 @@ export class StatefulMarkdownCell extends Disposable {
this.templateData.foldingIndicator.innerText = '';
break;
case CellFoldingState.Collapsed:
DOM.reset(this.templateData.foldingIndicator, ...renderCodiconsAsElement('$(chevron-right)'));
DOM.reset(this.templateData.foldingIndicator, ...renderCodicons('$(chevron-right)'));
break;
case CellFoldingState.Expanded:
DOM.reset(this.templateData.foldingIndicator, ...renderCodiconsAsElement('$(chevron-down)'));
DOM.reset(this.templateData.foldingIndicator, ...renderCodicons('$(chevron-down)'));
break;
default:

View file

@ -312,12 +312,12 @@ export class NotebookViewModel extends Disposable implements EditorFoldingStateD
if (change.kind === NotebookCellsChangeType.ModelChange || change.kind === NotebookCellsChangeType.Initialize) {
changes = change.changes;
compute(changes, e.synchronous);
return;
continue;
} else if (change.kind === NotebookCellsChangeType.Move) {
compute([[change.index, change.length, []]], e.synchronous);
compute([[change.newIdx, 0, change.cells]], e.synchronous);
} else {
return;
continue;
}
}
}));
@ -625,7 +625,7 @@ export class NotebookViewModel extends Disposable implements EditorFoldingStateD
createCell(index: number, source: string, language: string, type: CellKind, metadata: NotebookCellMetadata | undefined, outputs: IProcessedOutput[], synchronous: boolean, pushUndoStop: boolean = true, previouslyFocused: ICellViewModel[] = []): CellViewModel {
const beforeSelections = previouslyFocused.map(e => e.handle);
this._notebook.applyEdit(this._notebook.versionId, [
this._notebook.applyEdits(this._notebook.versionId, [
{
editType: CellEditType.Replace,
index,
@ -663,7 +663,7 @@ export class NotebookViewModel extends Disposable implements EditorFoldingStateD
}
}
this._notebook.applyEdit(this._notebook.versionId, [
this._notebook.applyEdits(this._notebook.versionId, [
{
editType: CellEditType.Replace,
index: index,
@ -691,7 +691,7 @@ export class NotebookViewModel extends Disposable implements EditorFoldingStateD
return false;
}
this._notebook.applyEdit(this._notebook.versionId, [
this._notebook.applyEdits(this._notebook.versionId, [
{
editType: CellEditType.Move,
index,
@ -785,7 +785,7 @@ export class NotebookViewModel extends Disposable implements EditorFoldingStateD
const editorSelections = cell.getSelections();
const language = cell.language;
const kind = cell.cellKind;
this._notebook.applyEdit(this._notebook.versionId, [
this._notebook.applyEdits(this._notebook.versionId, [
{
editType: CellEditType.CellContent,
index,
@ -957,11 +957,15 @@ export class NotebookViewModel extends Disposable implements EditorFoldingStateD
getEditorViewState(): INotebookEditorViewState {
const editingCells: { [key: number]: boolean } = {};
this._viewCells.filter(cell => cell.editState === CellEditState.Editing).forEach(cell => editingCells[cell.model.handle] = true);
this._viewCells.forEach((cell, i) => {
if (cell.editState === CellEditState.Editing) {
editingCells[i] = true;
}
});
const editorViewStates: { [key: number]: editorCommon.ICodeEditorViewState } = {};
this._viewCells.map(cell => ({ handle: cell.model.handle, state: cell.saveEditorViewState() })).forEach(viewState => {
this._viewCells.map(cell => ({ handle: cell.model.handle, state: cell.saveEditorViewState() })).forEach((viewState, i) => {
if (viewState.state) {
editorViewStates[viewState.handle] = viewState.state;
editorViewStates[i] = viewState.state;
}
});
@ -977,8 +981,8 @@ export class NotebookViewModel extends Disposable implements EditorFoldingStateD
}
this._viewCells.forEach((cell, index) => {
const isEditing = viewState.editingCells && viewState.editingCells[cell.handle];
const editorViewState = viewState.editorViewStates && viewState.editorViewStates[cell.handle];
const isEditing = viewState.editingCells && viewState.editingCells[index];
const editorViewState = viewState.editorViewStates && viewState.editorViewStates[index];
cell.editState = isEditing ? CellEditState.Editing : CellEditState.Preview;
const cellHeight = viewState.cellTotalHeights ? viewState.cellTotalHeights[index] : undefined;

View file

@ -291,7 +291,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel
this._operationManager.pushStackElement(label, selectionState);
}
applyEdit(modelVersionId: number, rawEdits: ICellEditOperation[], synchronous: boolean, beginSelectionState: number[] | undefined, endSelectionsComputer: () => number[] | undefined, computeUndoRedo: boolean = true): boolean {
applyEdits(modelVersionId: number, rawEdits: ICellEditOperation[], synchronous: boolean, beginSelectionState: number[] | undefined, endSelectionsComputer: () => number[] | undefined, computeUndoRedo: boolean = true): boolean {
if (modelVersionId !== this._versionId) {
return false;
}
@ -478,7 +478,26 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel
}
private _updateNotebookMetadata(metadata: NotebookDocumentMetadata, computeUndoRedo: boolean) {
const oldMetadata = this.metadata;
this.metadata = metadata;
if (computeUndoRedo) {
const that = this;
this._operationManager.pushEditOperation(new class implements IResourceUndoRedoElement {
readonly type: UndoRedoElementType.Resource = UndoRedoElementType.Resource;
get resource() {
return that.uri;
}
readonly label = 'Update Notebook Metadata';
undo() {
that._updateNotebookMetadata(oldMetadata, false);
}
redo() {
that._updateNotebookMetadata(metadata, false);
}
}(), undefined, undefined);
}
this._eventEmitter.emit({ kind: NotebookCellsChangeType.ChangeDocumentMetadata, metadata: this.metadata, transient: false }, true);
}
@ -565,11 +584,31 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel
private _changeCellLanguage(handle: number, languageId: string, computeUndoRedo: boolean) {
const cell = this._mapping.get(handle);
if (cell && cell.language !== languageId) {
cell.language = languageId;
this._eventEmitter.emit({ kind: NotebookCellsChangeType.ChangeLanguage, index: this._cells.indexOf(cell), language: languageId, transient: false }, true);
if (!cell || cell.language === languageId) {
return;
}
const oldLanguage = cell.language;
cell.language = languageId;
if (computeUndoRedo) {
const that = this;
this._operationManager.pushEditOperation(new class implements IResourceUndoRedoElement {
readonly type: UndoRedoElementType.Resource = UndoRedoElementType.Resource;
get resource() {
return that.uri;
}
readonly label = 'Update Cell Language';
undo() {
that._changeCellLanguage(cell.handle, oldLanguage, false);
}
redo() {
that._changeCellLanguage(cell.handle, languageId, false);
}
}(), undefined, undefined);
}
this._eventEmitter.emit({ kind: NotebookCellsChangeType.ChangeLanguage, index: this._cells.indexOf(cell), language: languageId, transient: false }, true);
}
private _spliceNotebookCellOutputs(cellHandle: number, splices: NotebookCellOutputsSplice[], computeUndoRedo: boolean): void {

View file

@ -30,18 +30,9 @@ export class NotebookModelReferenceCollection extends ReferenceCollection<Promis
super();
}
protected createReferencedObject(key: string, ...args: any[]): Promise<INotebookEditorModel> {
const resource = URI.parse(key);
let [viewType] = args as [string | undefined];
if (!viewType) {
viewType = this._notebookService.getContributedNotebookProviders(resource)[0]?.id;
}
if (!viewType) {
throw new Error('Missing viewType');
}
const model = this._instantiationService.createInstance(NotebookEditorModel, resource, viewType);
protected createReferencedObject(key: string, viewType: string): Promise<INotebookEditorModel> {
const uri = URI.parse(key);
const model = this._instantiationService.createInstance(NotebookEditorModel, uri, viewType);
const promise = model.load();
return promise;
}
@ -63,12 +54,26 @@ export class NotebookModelResolverService implements INotebookEditorModelResolve
private readonly _data: NotebookModelReferenceCollection;
constructor(
@IInstantiationService instantiationService: IInstantiationService
@IInstantiationService instantiationService: IInstantiationService,
@INotebookService private readonly _notebookService: INotebookService
) {
this._data = instantiationService.createInstance(NotebookModelReferenceCollection);
}
async resolve(resource: URI, viewType?: string): Promise<IReference<INotebookEditorModel>> {
const existingViewType = this._notebookService.getNotebookTextModel(resource)?.viewType;
if (!viewType) {
viewType = existingViewType ?? this._notebookService.getContributedNotebookProviders(resource)[0]?.id;
}
if (!viewType) {
throw new Error(`Missing viewType for '${resource}'`);
}
if (existingViewType && existingViewType !== viewType) {
throw new Error(`A notebook with view type '${existingViewType}' already exists for '${resource}', CANNOT create another notebook with view type ${viewType}`);
}
const reference = this._data.acquire(resource.toString(), viewType);
const model = await reference.object;
NotebookModelResolverService._autoReferenceDirtyModel(model, () => this._data.acquire(resource.toString(), viewType));

View file

@ -29,7 +29,7 @@ suite('NotebookTextModel', () => {
['var d = 4;', 'javascript', CellKind.Code, [], { editable: false }]
],
(editor, viewModel, textModel) => {
textModel.applyEdit(textModel.versionId, [
textModel.applyEdits(textModel.versionId, [
{ editType: CellEditType.Replace, index: 1, count: 0, cells: [new TestCell(viewModel.viewType, 5, 'var e = 5;', 'javascript', CellKind.Code, [], textModelService)] },
{ editType: CellEditType.Replace, index: 3, count: 0, cells: [new TestCell(viewModel.viewType, 6, 'var f = 6;', 'javascript', CellKind.Code, [], textModelService)] },
], true, undefined, () => undefined);
@ -54,7 +54,7 @@ suite('NotebookTextModel', () => {
['var d = 4;', 'javascript', CellKind.Code, [], { editable: false }]
],
(editor, viewModel, textModel) => {
textModel.applyEdit(textModel.versionId, [
textModel.applyEdits(textModel.versionId, [
{ editType: CellEditType.Replace, index: 1, count: 0, cells: [new TestCell(viewModel.viewType, 5, 'var e = 5;', 'javascript', CellKind.Code, [], textModelService)] },
{ editType: CellEditType.Replace, index: 1, count: 0, cells: [new TestCell(viewModel.viewType, 6, 'var f = 6;', 'javascript', CellKind.Code, [], textModelService)] },
], true, undefined, () => undefined);
@ -79,7 +79,7 @@ suite('NotebookTextModel', () => {
['var d = 4;', 'javascript', CellKind.Code, [], { editable: false }]
],
(editor, viewModel, textModel) => {
textModel.applyEdit(textModel.versionId, [
textModel.applyEdits(textModel.versionId, [
{ editType: CellEditType.Replace, index: 1, count: 1, cells: [] },
{ editType: CellEditType.Replace, index: 3, count: 1, cells: [] },
], true, undefined, () => undefined);
@ -102,7 +102,7 @@ suite('NotebookTextModel', () => {
['var d = 4;', 'javascript', CellKind.Code, [], { editable: false }]
],
(editor, viewModel, textModel) => {
textModel.applyEdit(textModel.versionId, [
textModel.applyEdits(textModel.versionId, [
{ editType: CellEditType.Replace, index: 1, count: 1, cells: [] },
{ editType: CellEditType.Replace, index: 3, count: 0, cells: [new TestCell(viewModel.viewType, 5, 'var e = 5;', 'javascript', CellKind.Code, [], textModelService)] },
], true, undefined, () => undefined);
@ -127,7 +127,7 @@ suite('NotebookTextModel', () => {
['var d = 4;', 'javascript', CellKind.Code, [], { editable: false }]
],
(editor, viewModel, textModel) => {
textModel.applyEdit(textModel.versionId, [
textModel.applyEdits(textModel.versionId, [
{ editType: CellEditType.Replace, index: 1, count: 1, cells: [] },
{ editType: CellEditType.Replace, index: 1, count: 0, cells: [new TestCell(viewModel.viewType, 5, 'var e = 5;', 'javascript', CellKind.Code, [], textModelService)] },
], true, undefined, () => undefined);
@ -152,7 +152,7 @@ suite('NotebookTextModel', () => {
['var d = 4;', 'javascript', CellKind.Code, [], { editable: false }]
],
(editor, viewModel, textModel) => {
textModel.applyEdit(textModel.versionId, [
textModel.applyEdits(textModel.versionId, [
{ editType: CellEditType.Replace, index: 1, count: 1, cells: [new TestCell(viewModel.viewType, 5, 'var e = 5;', 'javascript', CellKind.Code, [], textModelService)] },
], true, undefined, () => undefined);
@ -176,7 +176,7 @@ suite('NotebookTextModel', () => {
// invalid index 1
assert.throws(() => {
textModel.applyEdit(textModel.versionId, [{
textModel.applyEdits(textModel.versionId, [{
index: Number.MAX_VALUE,
editType: CellEditType.Output,
outputs: []
@ -185,14 +185,14 @@ suite('NotebookTextModel', () => {
// invalid index 2
assert.throws(() => {
textModel.applyEdit(textModel.versionId, [{
textModel.applyEdits(textModel.versionId, [{
index: -1,
editType: CellEditType.Output,
outputs: []
}], true, undefined, () => undefined);
});
textModel.applyEdit(textModel.versionId, [{
textModel.applyEdits(textModel.versionId, [{
index: 0,
editType: CellEditType.Output,
outputs: [{
@ -221,7 +221,7 @@ suite('NotebookTextModel', () => {
// invalid index 1
assert.throws(() => {
textModel.applyEdit(textModel.versionId, [{
textModel.applyEdits(textModel.versionId, [{
index: Number.MAX_VALUE,
editType: CellEditType.Metadata,
metadata: { editable: false }
@ -230,14 +230,14 @@ suite('NotebookTextModel', () => {
// invalid index 2
assert.throws(() => {
textModel.applyEdit(textModel.versionId, [{
textModel.applyEdits(textModel.versionId, [{
index: -1,
editType: CellEditType.Metadata,
metadata: { editable: false }
}], true, undefined, () => undefined);
});
textModel.applyEdit(textModel.versionId, [{
textModel.applyEdits(textModel.versionId, [{
index: 0,
editType: CellEditType.Metadata,
metadata: { editable: false },
@ -267,7 +267,7 @@ suite('NotebookTextModel', () => {
});
const version = textModel.versionId;
textModel.applyEdit(textModel.versionId, [
textModel.applyEdits(textModel.versionId, [
{ editType: CellEditType.Replace, index: 1, count: 1, cells: [] },
{ editType: CellEditType.Replace, index: 1, count: 0, cells: [new TestCell(viewModel.viewType, 5, 'var e = 5;', 'javascript', CellKind.Code, [], textModelService)] },
], true, undefined, () => [0]);
@ -304,7 +304,7 @@ suite('NotebookTextModel', () => {
});
const version = textModel.versionId;
textModel.applyEdit(textModel.versionId, [
textModel.applyEdits(textModel.versionId, [
{ editType: CellEditType.Replace, index: 1, count: 1, cells: [] },
{
index: 0,

View file

@ -19,7 +19,7 @@ import { IExtensionService } from 'vs/workbench/services/extensions/common/exten
import { FilterViewPaneContainer } from 'vs/workbench/browser/parts/views/viewsViewlet';
import { VIEWLET_ID } from 'vs/workbench/contrib/remote/common/remote.contribution';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IViewDescriptor, IViewsRegistry, Extensions, ViewContainerLocation, IViewContainersRegistry, IViewDescriptorService, IAddedViewDescriptorRef } from 'vs/workbench/common/views';
import { IViewDescriptor, IViewsRegistry, Extensions, ViewContainerLocation, IViewContainersRegistry, IViewDescriptorService, IAddedViewDescriptorRef, IViewsService } from 'vs/workbench/common/views';
import { Registry } from 'vs/platform/registry/common/platform';
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
import { IOpenerService } from 'vs/platform/opener/common/opener';
@ -37,14 +37,14 @@ import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
import { ReconnectionWaitEvent, PersistentConnectionEventType } from 'vs/platform/remote/common/remoteAgentConnection';
import Severity from 'vs/base/common/severity';
import { ReloadWindowAction } from 'vs/workbench/browser/actions/windowActions';
import { IDisposable } from 'vs/base/common/lifecycle';
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
import { SwitchRemoteViewItem, SwitchRemoteAction } from 'vs/workbench/contrib/remote/browser/explorerViewItems';
import { Action, IActionViewItem, IAction } from 'vs/base/common/actions';
import { isStringArray } from 'vs/base/common/types';
import { IRemoteExplorerService } from 'vs/workbench/services/remote/common/remoteExplorerService';
import { IRemoteExplorerService, MakeAddress } from 'vs/workbench/services/remote/common/remoteExplorerService';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
import { TunnelPanelDescriptor, TunnelViewModel, forwardedPortsViewEnabled } from 'vs/workbench/contrib/remote/browser/tunnelView';
import { TunnelPanelDescriptor, TunnelViewModel, forwardedPortsViewEnabled, OpenPortInBrowserAction } from 'vs/workbench/contrib/remote/browser/tunnelView';
import { ViewPane, IViewPaneOptions } from 'vs/workbench/browser/parts/views/viewPaneContainer';
import { IListVirtualDelegate } from 'vs/base/browser/ui/list/list';
import { ITreeRenderer, ITreeNode, IAsyncDataSource } from 'vs/base/browser/ui/tree/tree';
@ -56,6 +56,8 @@ import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
import { RemoteStatusIndicator } from 'vs/workbench/contrib/remote/browser/remoteIndicator';
import { inQuickPickContextKeyValue } from 'vs/workbench/browser/quickaccess';
import { Codicon, registerIcon } from 'vs/base/common/codicons';
import { INotificationService, IPromptChoice } from 'vs/platform/notification/common/notification';
import { UrlFinder } from 'vs/workbench/contrib/remote/browser/urlFinder';
import { ITerminalService } from 'vs/workbench/contrib/terminal/browser/terminal';
export interface HelpInformation {
@ -485,8 +487,7 @@ export class RemoteViewPaneContainer extends FilterViewPaneContainer implements
@IRemoteExplorerService private readonly remoteExplorerService: IRemoteExplorerService,
@IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService,
@IContextKeyService private readonly contextKeyService: IContextKeyService,
@IViewDescriptorService viewDescriptorService: IViewDescriptorService,
@ITerminalService private readonly terminalService: ITerminalService
@IViewDescriptorService viewDescriptorService: IViewDescriptorService
) {
super(VIEWLET_ID, remoteExplorerService.onDidChangeTargetType, configurationService, layoutService, telemetryService, storageService, instantiationService, themeService, contextMenuService, extensionService, contextService, viewDescriptorService);
this.addConstantViewDescriptors([this.helpPanelDescriptor]);
@ -561,7 +562,7 @@ export class RemoteViewPaneContainer extends FilterViewPaneContainer implements
// This context key is set to false in the constructor, but is expected to be changed by resolver extensions to enable the forwarded ports view.
const viewEnabled: boolean = !!forwardedPortsViewEnabled.getValue(this.contextKeyService);
if (this.environmentService.configuration.remoteAuthority && !this.tunnelPanelDescriptor && viewEnabled) {
this.tunnelPanelDescriptor = new TunnelPanelDescriptor(new TunnelViewModel(this.remoteExplorerService, this.terminalService), this.environmentService);
this.tunnelPanelDescriptor = new TunnelPanelDescriptor(new TunnelViewModel(this.remoteExplorerService), this.environmentService);
const viewsRegistry = Registry.as<IViewsRegistry>(Extensions.ViewsRegistry);
viewsRegistry.registerViews([this.tunnelPanelDescriptor!], this.viewContainer);
}
@ -840,6 +841,37 @@ class RemoteAgentConnectionStatusListener implements IWorkbenchContribution {
}
}
class AutomaticPortForwarding extends Disposable implements IWorkbenchContribution {
constructor(
@ITerminalService readonly terminalService: ITerminalService,
@INotificationService readonly notificationService: INotificationService,
@IOpenerService readonly openerService: IOpenerService,
@IViewsService readonly viewsService: IViewsService,
@IRemoteExplorerService readonly remoteExplorerService: IRemoteExplorerService
) {
super();
const urlFinder = this._register(new UrlFinder(terminalService));
this._register(urlFinder.onDidMatchLocalUrl(async (localUrl) => {
const forwarded = await this.remoteExplorerService.forward(localUrl);
if (forwarded) {
const address = MakeAddress(forwarded.tunnelRemoteHost, forwarded.tunnelRemotePort);
const message = nls.localize('remote.tunnelsView.automaticForward', "{0} has been forwarded to {1} locally.",
address, forwarded.localAddress);
const browserChoice: IPromptChoice = {
label: OpenPortInBrowserAction.LABEL,
run: () => OpenPortInBrowserAction.run(this.remoteExplorerService.tunnelModel, openerService, address)
};
const showChoice: IPromptChoice = {
label: nls.localize('remote.tunnelsView.showView', "Show Tunnels View"),
run: () => viewsService.openViewContainer(VIEWLET_ID)
};
notificationService.prompt(Severity.Info, message, [browserChoice, showChoice]);
}
}));
}
}
const workbenchContributionsRegistry = Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench);
workbenchContributionsRegistry.registerWorkbenchContribution(RemoteAgentConnectionStatusListener, LifecyclePhase.Eventually);
workbenchContributionsRegistry.registerWorkbenchContribution(RemoteStatusIndicator, LifecyclePhase.Starting);
workbenchContributionsRegistry.registerWorkbenchContribution(AutomaticPortForwarding, LifecyclePhase.Eventually);

View file

@ -42,8 +42,6 @@ import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { ActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems';
import { ITerminalService } from 'vs/workbench/contrib/terminal/browser/terminal';
import { UrlFinder } from 'vs/workbench/contrib/remote/browser/urlFinder';
export const forwardedPortsViewEnabled = new RawContextKey<boolean>('forwardedPortsViewEnabled', false);
@ -74,8 +72,7 @@ export class TunnelViewModel extends Disposable implements ITunnelViewModel {
private _candidates: Map<string, { host: string, port: number, detail: string }> = new Map();
constructor(
@IRemoteExplorerService private readonly remoteExplorerService: IRemoteExplorerService,
@ITerminalService readonly terminalService: ITerminalService) {
@IRemoteExplorerService private readonly remoteExplorerService: IRemoteExplorerService) {
super();
this.model = remoteExplorerService.tunnelModel;
this._register(this.model.onForwardPort(() => this._onForwardedPortsChanged.fire()));
@ -89,11 +86,6 @@ export class TunnelViewModel extends Disposable implements ITunnelViewModel {
remotePort: 0,
description: ''
};
const urlFinder = this._register(new UrlFinder(terminalService));
this._register(urlFinder.onDidMatchLocalUrl(localUrl => {
this.model.forward(localUrl);
}));
}
async groups(): Promise<ITunnelGroup[]> {
@ -866,7 +858,7 @@ namespace ClosePortAction {
}
}
namespace OpenPortInBrowserAction {
export namespace OpenPortInBrowserAction {
export const ID = 'remote.tunnel.open';
export const LABEL = nls.localize('remote.tunnel.open', "Open in Browser");
@ -876,15 +868,19 @@ namespace OpenPortInBrowserAction {
const model = accessor.get(IRemoteExplorerService).tunnelModel;
const openerService = accessor.get(IOpenerService);
const key = MakeAddress(arg.remoteHost, arg.remotePort);
const tunnel = model.forwarded.get(key) || model.detected.get(key);
let address: string | undefined;
if (tunnel && tunnel.localAddress && (address = model.address(tunnel.remoteHost, tunnel.remotePort))) {
return openerService.open(URI.parse('http://' + address));
}
return Promise.resolve();
return run(model, openerService, key);
}
};
}
export function run(model: TunnelModel, openerService: IOpenerService, key: string) {
const tunnel = model.forwarded.get(key) || model.detected.get(key);
let address: string | undefined;
if (tunnel && tunnel.localAddress && (address = model.address(tunnel.remoteHost, tunnel.remotePort))) {
return openerService.open(URI.parse('http://' + address));
}
return Promise.resolve();
}
}
namespace CopyAddressAction {

Some files were not shown because too many files have changed in this diff Show more