Merge from vscode 011858832762aaff245b2336fb1c38166e7a10fb (#4663)

This commit is contained in:
Anthony Dresser
2019-03-22 13:07:54 -07:00
committed by GitHub
parent f5c9174c2f
commit 4a87a24235
296 changed files with 2531 additions and 2472 deletions
@@ -80,10 +80,6 @@ export class ServerTreeActionProvider extends ContributableActionProvider {
return false;
}
public getSecondaryActions(tree: ITree, element: any): IAction[] {
return super.getSecondaryActions(tree, element);
}
/**
* Return actions for connection elements
*/
@@ -40,10 +40,6 @@ export class TaskHistoryActionProvider extends ContributableActionProvider {
return false;
}
public getSecondaryActions(tree: ITree, element: any): IAction[] {
return super.getSecondaryActions(tree, element);
}
/**
* Return actions for history task
*/
@@ -64,4 +60,4 @@ export class TaskHistoryActionProvider extends ContributableActionProvider {
return actions;
}
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
// Defined a subset of ES6 built ins that run in IE11
+9 -9
View File
@@ -6,7 +6,7 @@
declare module 'spdlog' {
export const version: string;
export function setAsyncMode(bufferSize: number, flushInterval: number);
export function setAsyncMode(bufferSize: number, flushInterval: number): void;
export enum LogLevel {
CRITICAL,
@@ -21,14 +21,14 @@ declare module 'spdlog' {
export class RotatingLogger {
constructor(name: string, filename: string, filesize: number, filecount: number);
trace(message: string);
debug(message: string);
info(message: string);
warn(message: string);
error(message: string);
critical(message: string);
setLevel(level: number);
clearFormatters();
trace(message: string): void;
debug(message: string): void;
info(message: string): void;
warn(message: string): void;
error(message: string): void;
critical(message: string): void;
setLevel(level: number): void;
clearFormatters(): void;
/**
* A synchronous operation to flush the contents into file
*/
+1 -1
View File
@@ -5,5 +5,5 @@
declare module 'sudo-prompt' {
export function exec(cmd: string, options: { name?: string, icns?: string }, callback: (error: string, stdout: string, stderr: string) => void);
export function exec(cmd: string, options: { name?: string, icns?: string }, callback: (error: string, stdout: string, stderr: string) => void): void;
}
+3 -3
View File
@@ -31,9 +31,9 @@ declare module 'yauzl' {
}
export class ZipFile extends EventEmitter {
readEntry();
openReadStream(entry: Entry, callback: (err?: Error, stream?: Readable) => void);
close();
readEntry(): void;
openReadStream(entry: Entry, callback: (err?: Error, stream?: Readable) => void): void;
close(): void;
isOpen: boolean;
entryCount: number;
comment: string;
+3 -3
View File
@@ -8,8 +8,8 @@ declare module 'yazl' {
class ZipFile {
outputStream: stream.Stream;
addBuffer(buffer: Buffer, path: string);
addFile(localPath: string, path: string);
end();
addBuffer(buffer: Buffer, path: string): void;
addFile(localPath: string, path: string): void;
end(): void;
}
}
+1 -1
View File
@@ -25,7 +25,7 @@ export class ContextSubMenu extends SubmenuAction {
export interface IContextMenuDelegate {
getAnchor(): HTMLElement | { x: number; y: number; width?: number; height?: number; };
getActions(): Array<IAction | ContextSubMenu>;
getActionItem?(action: IAction): IActionItem | null;
getActionItem?(action: IAction): IActionItem | undefined;
getActionsContext?(event?: IContextMenuEvent): any;
getKeyBinding?(action: IAction): ResolvedKeybinding | undefined;
getMenuClassName?(): string;
@@ -364,7 +364,7 @@ export interface ActionTrigger {
}
export interface IActionItemProvider {
(action: IAction): IActionItem | null;
(action: IAction): IActionItem | undefined;
}
export interface IActionBarOptions {
@@ -609,7 +609,7 @@ export class ActionBar extends Disposable implements IActionRunner {
e.stopPropagation();
}));
let item: IActionItem | null = null;
let item: IActionItem | undefined;
if (this.options.actionItemProvider) {
item = this.options.actionItemProvider(action);
@@ -118,7 +118,7 @@ export class ContextView extends Disposable {
this._register(toDisposable(() => this.setContainer(null)));
}
public setContainer(container: HTMLElement | null): void {
setContainer(container: HTMLElement | null): void {
if (this.container) {
this.toDisposeOnSetContainer = dispose(this.toDisposeOnSetContainer);
this.container.removeChild(this.view);
@@ -146,7 +146,7 @@ export class ContextView extends Disposable {
}
}
public show(delegate: IDelegate): void {
show(delegate: IDelegate): void {
if (this.isVisible()) {
this.hide();
}
@@ -173,7 +173,7 @@ export class ContextView extends Disposable {
}
}
public layout(): void {
layout(): void {
if (!this.isVisible()) {
return;
}
@@ -258,7 +258,7 @@ export class ContextView extends Disposable {
this.view.style.width = 'initial';
}
public hide(data?: any): void {
hide(data?: any): void {
if (this.delegate && this.delegate.onHide) {
this.delegate.onHide(data);
}
@@ -288,7 +288,7 @@ export class ContextView extends Disposable {
}
}
public dispose(): void {
dispose(): void {
this.hide();
super.dispose();
+1 -1
View File
@@ -247,7 +247,7 @@ export class DropdownMenu extends BaseDropdown {
getAnchor: () => this.element,
getActions: () => this.actions,
getActionsContext: () => this.menuOptions ? this.menuOptions.context : null,
getActionItem: action => this.menuOptions && this.menuOptions.actionItemProvider ? this.menuOptions.actionItemProvider(action) : null,
getActionItem: action => this.menuOptions && this.menuOptions.actionItemProvider ? this.menuOptions.actionItemProvider(action) : undefined,
getKeyBinding: action => this.menuOptions && this.menuOptions.getKeyBinding ? this.menuOptions.getKeyBinding(action) : undefined,
getMenuClassName: () => this.menuClassName,
onHide: () => this.onHide(),
+1 -1
View File
@@ -63,7 +63,7 @@ const DefaultOptions = {
setRowLineHeight: true,
supportDynamicHeights: false,
dnd: {
getDragElements(e) { return [e]; },
getDragElements<T>(e: T) { return [e]; },
getDragURI() { return null; },
onDragStart(): void { },
onDragOver() { return false; },
@@ -860,8 +860,8 @@ export class SelectBoxList implements ISelectBoxDelegate, IListVirtualDelegate<I
this.selectionDetailsPane.innerText = '';
const selectedIndex = e.indexes[0];
const description = this.options[selectedIndex].description || null;
const descriptionIsMarkdown = this.options[selectedIndex].descriptionIsMarkdown || null;
const description = this.options[selectedIndex].description;
const descriptionIsMarkdown = this.options[selectedIndex].descriptionIsMarkdown;
if (description) {
if (descriptionIsMarkdown) {
+2 -2
View File
@@ -75,10 +75,10 @@ export class ToolBar extends Disposable {
);
this.toggleMenuActionItem!.setActionContext(this.actionBar.context);
return this.toggleMenuActionItem || null;
return this.toggleMenuActionItem;
}
return options.actionItemProvider ? options.actionItemProvider(action) : null;
return options.actionItemProvider ? options.actionItemProvider(action) : undefined;
}
}));
}
+3 -3
View File
@@ -805,7 +805,7 @@ class Trait<T> {
onDidModelSplice({ insertedNodes, deletedNodes }: ITreeModelSpliceEvent<T, any>): void {
if (!this.identityProvider) {
const set = this.createNodeSet();
const visit = node => set.delete(node);
const visit = (node: ITreeNode<T, any>) => set.delete(node);
deletedNodes.forEach(node => dfs(node, visit));
this.set(values(set));
return;
@@ -816,8 +816,8 @@ class Trait<T> {
this.nodes.forEach(node => nodesByIdentity.set(identityProvider.getId(node.element).toString(), node));
const toDeleteByIdentity = new Map<string, ITreeNode<T, any>>();
const toRemoveSetter = node => toDeleteByIdentity.set(identityProvider.getId(node.element).toString(), node);
const toRemoveDeleter = node => toDeleteByIdentity.delete(identityProvider.getId(node.element).toString());
const toRemoveSetter = (node: ITreeNode<T, any>) => toDeleteByIdentity.set(identityProvider.getId(node.element).toString(), node);
const toRemoveDeleter = (node: { element: T; }) => toDeleteByIdentity.delete(identityProvider.getId(node.element).toString());
deletedNodes.forEach(node => dfs(node, toRemoveSetter));
insertedNodes.forEach(node => dfs(node, toRemoveDeleter));
+37 -39
View File
@@ -16,6 +16,7 @@ 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 { toggleClass } from 'vs/base/browser/dom';
import { values } from 'vs/base/common/map';
interface IAsyncDataTreeNode<TInput, T> {
element: TInput | T;
@@ -26,7 +27,6 @@ interface IAsyncDataTreeNode<TInput, T> {
hasChildren: boolean;
stale: boolean;
slow: boolean;
disposed: boolean;
}
interface IAsyncDataTreeNodeRequiredProps<TInput, T> extends Partial<IAsyncDataTreeNode<TInput, T>> {
@@ -41,7 +41,6 @@ function createAsyncDataTreeNode<TInput, T>(props: IAsyncDataTreeNodeRequiredPro
children: [],
loading: false,
stale: true,
disposed: false,
slow: false
};
}
@@ -274,6 +273,11 @@ interface IAsyncDataTreeViewStateContext<TInput, T> {
readonly focus: IAsyncDataTreeNode<TInput, T>[];
}
function dfs<TInput, T>(node: IAsyncDataTreeNode<TInput, T>, fn: (node: IAsyncDataTreeNode<TInput, T>) => void): void {
fn(node);
node.children.forEach(child => dfs(child, fn));
}
export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable {
private readonly tree: ObjectTree<IAsyncDataTreeNode<TInput, T>, TFilterData>;
@@ -629,11 +633,6 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
}
private async refreshNode(node: IAsyncDataTreeNode<TInput, T>, recursive: boolean, viewStateContext?: IAsyncDataTreeViewStateContext<TInput, T>): Promise<void> {
if (node.disposed) {
console.error('Async data tree node is disposed');
return;
}
let result: Promise<void> | undefined;
this.subTreeRefreshPromises.forEach((refreshPromise, refreshNode) => {
@@ -748,37 +747,47 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
return [];
}
let nodeChildren: Map<string, IAsyncDataTreeNode<TInput, T>> | undefined;
const nodesToForget = new Map<T, IAsyncDataTreeNode<TInput, T>>();
const childrenTreeNodesById = new Map<string, ITreeNode<IAsyncDataTreeNode<TInput, T> | null, TFilterData>>();
if (this.identityProvider) {
nodeChildren = new Map();
for (const child of node.children) {
nodesToForget.set(child.element as T, child);
for (const child of node.children) {
nodeChildren.set(child.id!, child);
if (this.identityProvider) {
childrenTreeNodesById.set(child.id!, this.tree.getNode(child));
}
}
let childrenToRefresh: IAsyncDataTreeNode<TInput, T>[] = [];
const childrenToRefresh: IAsyncDataTreeNode<TInput, T>[] = [];
const children = childrenElements.map<IAsyncDataTreeNode<TInput, T>>(element => {
if (!this.identityProvider) {
return createAsyncDataTreeNode({
element,
parent: node,
hasChildren: !!this.dataSource.hasChildren(element),
hasChildren: !!this.dataSource.hasChildren(element)
});
}
const id = this.identityProvider.getId(element).toString();
const asyncDataTreeNode = nodeChildren!.get(id);
const childNode = childrenTreeNodesById.get(id);
if (childNode) {
const asyncDataTreeNode = childNode.element!;
nodesToForget.delete(asyncDataTreeNode.element as T);
this.nodes.delete(asyncDataTreeNode.element as T);
this.nodes.set(element, asyncDataTreeNode);
if (asyncDataTreeNode) {
asyncDataTreeNode.element = element;
asyncDataTreeNode.stale = asyncDataTreeNode.stale || recursive;
asyncDataTreeNode.hasChildren = !!this.dataSource.hasChildren(element);
if (recursive && !this.tree.isCollapsed(asyncDataTreeNode)) {
childrenToRefresh.push(asyncDataTreeNode);
if (recursive) {
if (childNode.collapsed) {
dfs(asyncDataTreeNode, node => node.stale = true);
} else {
childrenToRefresh.push(asyncDataTreeNode);
}
}
return asyncDataTreeNode;
@@ -806,33 +815,22 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
return childAsyncDataTreeNode;
});
for (const node of values(nodesToForget)) {
dfs(node, node => this.nodes.delete(node.element as T));
}
for (const child of children) {
this.nodes.set(child.element as T, child);
}
node.children.splice(0, node.children.length, ...children);
return childrenToRefresh;
}
private render(node: IAsyncDataTreeNode<TInput, T>, viewStateContext?: IAsyncDataTreeViewStateContext<TInput, T>): void {
const insertedElements = new Set<T>();
const onDidCreateNode = (treeNode: ITreeNode<IAsyncDataTreeNode<TInput, T>, TFilterData>) => {
if (treeNode.element.element) {
insertedElements.add(treeNode.element.element as T);
this.nodes.set(treeNode.element.element as T, treeNode.element);
}
};
const onDidDeleteNode = (treeNode: ITreeNode<IAsyncDataTreeNode<TInput, T>, TFilterData>) => {
if (treeNode.element.element) {
if (!insertedElements.has(treeNode.element.element as T)) {
treeNode.element.disposed = true;
this.nodes.delete(treeNode.element.element as T);
}
}
};
const children = node.children.map(c => asTreeElement(c, viewStateContext));
this.tree.setChildren(node === this.root ? null : node, children, onDidCreateNode, onDidDeleteNode);
this.tree.setChildren(node === this.root ? null : node, children);
this._onDidRender.fire();
}
+11 -2
View File
@@ -198,8 +198,17 @@ export class ObjectTreeModel<T extends NonNullable<any>, TFilterData extends Non
}
getNode(element: T | null = null): ITreeNode<T | null, TFilterData> {
const location = this.getElementLocation(element);
return this.model.getNode(location);
if (element === null) {
return this.model.getNode(this.model.rootRef);
}
const node = this.nodes.get(element);
if (!node) {
throw new Error(`Tree element not found: ${element}`);
}
return node;
}
getNodeLocation(node: ITreeNode<T, TFilterData>): T {
+2 -3
View File
@@ -404,9 +404,8 @@ export function firstIndex<T>(array: ReadonlyArray<T>, fn: (item: T) => boolean)
}
export function first<T>(array: ReadonlyArray<T>, fn: (item: T) => boolean, notFoundValue: T): T;
export function first<T>(array: ReadonlyArray<T>, fn: (item: T) => boolean): T | null;
export function first<T>(array: ReadonlyArray<T>, fn: (item: T) => boolean, notFoundValue: T | null): T | null;
export function first<T>(array: ReadonlyArray<T>, fn: (item: T) => boolean, notFoundValue: T | null = null): T | null {
export function first<T>(array: ReadonlyArray<T>, fn: (item: T) => boolean): T | undefined;
export function first<T>(array: ReadonlyArray<T>, fn: (item: T) => boolean, notFoundValue: T | undefined = undefined): T | undefined {
const index = firstIndex(array, fn);
return index < 0 ? notFoundValue : array[index];
}
+6 -6
View File
@@ -178,7 +178,7 @@ export class Delayer<T> implements IDisposable {
private timeout: any;
private completionPromise: Promise<any> | null;
private doResolve: ((value?: any | Promise<any>) => void) | null;
private doReject: (err: any) => void;
private doReject?: (err: any) => void;
private task: ITask<T | Promise<T>> | null;
constructor(public defaultDelay: number) {
@@ -222,7 +222,7 @@ export class Delayer<T> implements IDisposable {
this.cancelTimeout();
if (this.completionPromise) {
this.doReject(errors.canceled());
this.doReject!(errors.canceled());
this.completionPromise = null;
}
}
@@ -282,7 +282,7 @@ export class Barrier {
private _isOpen: boolean;
private _promise: Promise<boolean>;
private _completePromise: (v: boolean) => void;
private _completePromise!: (v: boolean) => void;
constructor() {
this._isOpen = false;
@@ -731,8 +731,8 @@ export class IdleValue<T> {
private readonly _executor: () => void;
private readonly _handle: IDisposable;
private _didRun: boolean;
private _value: T;
private _didRun: boolean = false;
private _value?: T;
private _error: any;
constructor(executor: () => T) {
@@ -760,7 +760,7 @@ export class IdleValue<T> {
if (this._error) {
throw this._error;
}
return this._value;
return this._value!;
}
}
+1 -1
View File
@@ -87,7 +87,7 @@ class MutableToken implements CancellationToken {
export class CancellationTokenSource {
private _token: CancellationToken;
private _token?: CancellationToken;
get token(): CancellationToken {
if (!this._token) {
+2 -2
View File
@@ -260,7 +260,7 @@ export class Color {
}
readonly rgba: RGBA;
private _hsla: HSLA;
private _hsla?: HSLA;
get hsla(): HSLA {
if (this._hsla) {
return this._hsla;
@@ -269,7 +269,7 @@ export class Color {
}
}
private _hsva: HSVA;
private _hsva?: HSVA;
get hsva(): HSVA {
if (this._hsva) {
return this._hsva;
+11 -1
View File
@@ -119,6 +119,15 @@ function isWhitespace(code: number): boolean {
);
}
const wordSeparators = new Set<number>();
'`~!@#$%^&*()-=+[{]}\\|;:\'",.<>/?'
.split('')
.forEach(s => wordSeparators.add(s.charCodeAt(0)));
function isWordSeparator(code: number): boolean {
return wordSeparators.has(code);
}
function isAlphanumeric(code: number): boolean {
return isLower(code) || isUpper(code) || isNumber(code);
}
@@ -308,7 +317,8 @@ function _matchesWords(word: string, target: string, i: number, j: number, conti
function nextWord(word: string, start: number): number {
for (let i = start; i < word.length; i++) {
const c = word.charCodeAt(i);
if (isWhitespace(c) || (i > 0 && isWhitespace(word.charCodeAt(i - 1)))) {
if (isWhitespace(c) || (i > 0 && isWhitespace(word.charCodeAt(i - 1))) ||
isWordSeparator(c) || (i > 0 && isWordSeparator(word.charCodeAt(i - 1)))) {
return i;
}
}
+11 -12
View File
@@ -43,7 +43,7 @@ const CHAR_QUESTION_MARK = 63; /* ? */
class ErrorInvalidArgType extends Error {
code: 'ERR_INVALID_ARG_TYPE';
constructor(name: string, expected: string, actual: string) {
constructor(name: string, expected: string, actual: any) {
// determiner: 'must be' or 'must not be'
let determiner;
if (typeof expected === 'string' && expected.indexOf('not ') === 0) {
@@ -53,36 +53,35 @@ class ErrorInvalidArgType extends Error {
determiner = 'must be';
}
let msg;
const type = name.indexOf('.') !== -1 ? 'property' : 'argument';
msg = `The "${name}" ${type} ${determiner} of type ${expected}`;
let msg = `The "${name}" ${type} ${determiner} of type ${expected}`;
msg += `. Received type ${typeof actual}`;
super(msg);
}
}
function validateString(value: string, name) {
function validateString(value: string, name: string) {
if (typeof value !== 'string') {
throw new ErrorInvalidArgType(name, 'string', value);
}
}
function isPathSeparator(code) {
function isPathSeparator(code: number) {
return code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH;
}
function isPosixPathSeparator(code) {
function isPosixPathSeparator(code: number) {
return code === CHAR_FORWARD_SLASH;
}
function isWindowsDeviceRoot(code) {
function isWindowsDeviceRoot(code: number) {
return code >= CHAR_UPPERCASE_A && code <= CHAR_UPPERCASE_Z ||
code >= CHAR_LOWERCASE_A && code <= CHAR_LOWERCASE_Z;
}
// Resolves . and .. elements in a path with directory names
function normalizeString(path, allowAboveRoot, separator, isPathSeparator) {
function normalizeString(path: string, allowAboveRoot: boolean, separator: string, isPathSeparator: (code?: number) => boolean) {
let res = '';
let lastSegmentLength = 0;
let lastSlash = -1;
@@ -155,7 +154,7 @@ function normalizeString(path, allowAboveRoot, separator, isPathSeparator) {
return res;
}
function _format(sep, pathObject) {
function _format(sep: string, pathObject: ParsedPath) {
const dir = pathObject.dir || pathObject.root;
const base = pathObject.base ||
((pathObject.name || '') + (pathObject.ext || ''));
@@ -185,7 +184,7 @@ interface IPath {
dirname(path: string): string;
basename(path: string, ext?: string): string;
extname(path: string): string;
format(pathObject): string;
format(pathObject: ParsedPath): string;
parse(path: string): ParsedPath;
toNamespacedPath(path: string): string;
sep: '\\' | '/';
@@ -501,7 +500,7 @@ export const win32: IPath = {
}
let joined;
let firstPart;
let firstPart: string | undefined;
for (let i = 0; i < paths.length; ++i) {
const arg = paths[i];
validateString(arg, 'path');
@@ -534,7 +533,7 @@ export const win32: IPath = {
// path.join('//server', 'share') -> '\\\\server\\share\\')
let needsReplace = true;
let slashCount = 0;
if (isPathSeparator(firstPart.charCodeAt(0))) {
if (typeof firstPart === 'string' && isPathSeparator(firstPart.charCodeAt(0))) {
++slashCount;
const firstLen = firstPart.length;
if (firstLen > 1) {
+2 -2
View File
@@ -377,8 +377,8 @@ export class SmoothScrollingOperation {
private readonly _startTime: number;
public animationFrameDisposable: IDisposable | null;
private scrollLeft: IAnimation;
private scrollTop: IAnimation;
private scrollLeft!: IAnimation;
private scrollTop!: IAnimation;
protected constructor(from: ISmoothScrollPosition, to: ISmoothScrollPosition, startTime: number, duration: number) {
this.from = from;
+1 -1
View File
@@ -174,7 +174,7 @@ export function create(ctor: Function, ...args: any[]): any {
}
// https://stackoverflow.com/a/32235645/1499159
function isNativeClass(thing): boolean {
function isNativeClass(thing: any): boolean {
return typeof thing === 'function'
&& thing.hasOwnProperty('prototype')
&& !thing.hasOwnProperty('arguments');
+2 -2
View File
@@ -20,8 +20,8 @@ import { TernarySearchTree } from 'vs/base/common/map';
// Sun xVM VirtualBox 08-00-27
export const virtualMachineHint: { value(): number } = new class {
private _virtualMachineOUIs: TernarySearchTree<boolean>;
private _value: number;
private _virtualMachineOUIs?: TernarySearchTree<boolean>;
private _value?: number;
private _isVirtualMachineMacAdress(mac: string): boolean {
if (!this._virtualMachineOUIs) {
+4
View File
@@ -59,6 +59,10 @@ export function lstat(path: string): Promise<fs.Stats> {
return nfcall(fs.lstat, path);
}
export function move(oldPath: string, newPath: string): Promise<void> {
return nfcall(extfs.mv, oldPath, newPath);
}
export function rename(oldPath: string, newPath: string): Promise<void> {
return nfcall(fs.rename, oldPath, newPath);
}
@@ -9,7 +9,7 @@ import { URI } from 'vs/base/common/uri';
import { ITree, IActionProvider } from 'vs/base/parts/tree/browser/tree';
import { IconLabel, IIconLabelValueOptions } from 'vs/base/browser/ui/iconLabel/iconLabel';
import { IQuickNavigateConfiguration, IModel, IDataSource, IFilter, IAccessiblityProvider, IRenderer, IRunner, Mode, IEntryRunContext } from 'vs/base/parts/quickopen/common/quickOpen';
import { Action, IAction, IActionRunner, IActionItem } from 'vs/base/common/actions';
import { IAction, IActionRunner } from 'vs/base/common/actions';
import { compareAnything } from 'vs/base/common/comparers';
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
import { HighlightedLabel } from 'vs/base/browser/ui/highlightedlabel/highlightedLabel';
@@ -291,18 +291,6 @@ class NoActionProvider implements IActionProvider {
getActions(tree: ITree, element: any): IAction[] | null {
return null;
}
hasSecondaryActions(tree: ITree, element: any): boolean {
return false;
}
getSecondaryActions(tree: ITree, element: any): IAction[] | null {
return null;
}
getActionItem(tree: ITree, element: any, action: Action): IActionItem | null {
return null;
}
}
export interface IQuickOpenEntryTemplateData {
+9 -91
View File
@@ -9,7 +9,7 @@ import * as Keyboard from 'vs/base/browser/keyboardEvent';
import { INavigator } from 'vs/base/common/iterator';
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
import { Event } from 'vs/base/common/event';
import { IAction, IActionItem } from 'vs/base/common/actions';
import { IAction } from 'vs/base/common/actions';
import { Color } from 'vs/base/common/color';
import { IItemCollapseEvent, IItemExpandEvent } from 'vs/base/parts/tree/browser/treeModel';
import { IDragAndDropData } from 'vs/base/browser/dnd';
@@ -169,81 +169,21 @@ export interface ITree {
*/
getHighlight(includeHidden?: boolean): any;
/**
* Returns whether an element is highlighted or not.
*/
isHighlighted(element: any): boolean;
/**
* Clears the highlight.
*/
clearHighlight(eventPayload?: any): void;
/**
* Selects an element.
*/
select(element: any, eventPayload?: any): void;
/**
* Selects a range of elements.
*/
selectRange(fromElement: any, toElement: any, eventPayload?: any): void;
/**
* Deselects a range of elements.
*/
deselectRange(fromElement: any, toElement: any, eventPayload?: any): void;
/**
* Selects several elements.
*/
selectAll(elements: any[], eventPayload?: any): void;
/**
* Deselects an element.
*/
deselect(element: any, eventPayload?: any): void;
/**
* Deselects several elements.
*/
deselectAll(elements: any[], eventPayload?: any): void;
/**
* Replaces the current selection with the given elements.
*/
setSelection(elements: any[], eventPayload?: any): void;
/**
* Toggles the element's selection.
*/
toggleSelection(element: any, eventPayload?: any): void;
/**
* Returns the currently selected elements.
*/
getSelection(includeHidden?: boolean): any[];
/**
* Returns whether an element is selected or not.
*/
isSelected(element: any): boolean;
/**
* Selects the next `count`-nth element, in visible order.
*/
selectNext(count?: number, clearSelection?: boolean, eventPayload?: any): void;
/**
* Selects the previous `count`-nth element, in visible order.
*/
selectPrevious(count?: number, clearSelection?: boolean, eventPayload?: any): void;
/**
* Selects the currently selected element's parent.
*/
selectParent(clearSelection?: boolean, eventPayload?: any): void;
/**
* Clears the selection.
*/
@@ -254,11 +194,6 @@ export interface ITree {
*/
setFocus(element?: any, eventPayload?: any): void;
/**
* Returns whether an element is focused or not.
*/
isFocused(element: any): boolean;
/**
* Returns focused element.
*/
@@ -316,6 +251,7 @@ export interface ITree {
*/
clearFocus(eventPayload?: any): void;
// {{SQL CARBON EDIT}} @todo anthonydresser we need to refactor our code to not need these methods
/**
* Adds the trait to elements.
*/
@@ -327,14 +263,15 @@ export interface ITree {
removeTraits(trait: string, elements: any[]): void;
/**
* Toggles the element's trait.
* Selects an element.
*/
toggleTrait(trait: string, element: any): void;
select(element: any, eventPayload?: any): void;
/**
* Returns whether the element has the trait or not.
* Deselects an element.
*/
hasTrait(trait: string, element: any): boolean;
deselect(element: any, eventPayload?: any): void;
// {{SQL CARBON EDIT}} END
/**
* Returns a navigator which allows to discover the visible and
@@ -582,12 +519,14 @@ export interface IDragOverReaction {
autoExpand?: boolean;
}
// {{SQL CARBON EDIT}} @todo anthonydresser refactor to not need this
export const DRAG_OVER_REJECT: IDragOverReaction = { accept: false };
export const DRAG_OVER_ACCEPT: IDragOverReaction = { accept: true };
export const DRAG_OVER_ACCEPT_BUBBLE_UP: IDragOverReaction = { accept: true, bubble: DragOverBubble.BUBBLE_UP };
export const DRAG_OVER_ACCEPT_BUBBLE_DOWN = (autoExpand = false) => ({ accept: true, bubble: DragOverBubble.BUBBLE_DOWN, autoExpand });
export const DRAG_OVER_ACCEPT_BUBBLE_UP_COPY: IDragOverReaction = { accept: true, bubble: DragOverBubble.BUBBLE_UP, effect: DragOverEffect.COPY };
export const DRAG_OVER_ACCEPT_BUBBLE_DOWN_COPY = (autoExpand = false) => ({ accept: true, bubble: DragOverBubble.BUBBLE_DOWN, effect: DragOverEffect.COPY, autoExpand });
// {{SQL CARBON EDIT}} END
export interface IDragAndDrop {
@@ -635,12 +574,6 @@ export interface IFilter {
isVisible(tree: ITree, element: any): boolean;
}
export interface IElementCallback {
(tree: ITree, element: any): void;
}
export type ICallback = () => void;
export interface ISorter {
/**
@@ -730,19 +663,4 @@ export interface IActionProvider {
* Returns a promise of an array with the actions of the element that should show up in place right to the element in the tree.
*/
getActions(tree: ITree | null, element: any): IAction[] | null;
/**
* Returns whether or not the element has secondary actions. These show up once the user has expanded the element's action bar.
*/
hasSecondaryActions(tree: ITree, element: any): boolean;
/**
* Returns a promise of an array with the secondary actions of the element that should show up once the user has expanded the element's action bar.
*/
getSecondaryActions(tree: ITree, element: any): IAction[] | null;
/**
* Returns an action item to render an action.
*/
getActionItem(tree: ITree, element: any, action: IAction): IActionItem | null;
}
+6 -57
View File
@@ -230,50 +230,14 @@ export class Tree implements _.ITree {
return this.model.getHighlight();
}
public isHighlighted(element: any): boolean {
return this.model.isFocused(element);
}
public clearHighlight(eventPayload?: any): void {
this.model.setHighlight(null, eventPayload);
}
public select(element: any, eventPayload?: any): void {
this.model.select(element, eventPayload);
}
public selectRange(fromElement: any, toElement: any, eventPayload?: any): void {
this.model.selectRange(fromElement, toElement, eventPayload);
}
public deselectRange(fromElement: any, toElement: any, eventPayload?: any): void {
this.model.deselectRange(fromElement, toElement, eventPayload);
}
public selectAll(elements: any[], eventPayload?: any): void {
this.model.selectAll(elements, eventPayload);
}
public deselect(element: any, eventPayload?: any): void {
this.model.deselect(element, eventPayload);
}
public deselectAll(elements: any[], eventPayload?: any): void {
this.model.deselectAll(elements, eventPayload);
}
public setSelection(elements: any[], eventPayload?: any): void {
this.model.setSelection(elements, eventPayload);
}
public toggleSelection(element: any, eventPayload?: any): void {
this.model.toggleSelection(element, eventPayload);
}
public isSelected(element: any): boolean {
return this.model.isSelected(element);
}
public getSelection(): any[] {
return this.model.getSelection();
}
@@ -282,26 +246,10 @@ export class Tree implements _.ITree {
this.model.setSelection([], eventPayload);
}
public selectNext(count?: number, clearSelection?: boolean, eventPayload?: any): void {
this.model.selectNext(count, clearSelection, eventPayload);
}
public selectPrevious(count?: number, clearSelection?: boolean, eventPayload?: any): void {
this.model.selectPrevious(count, clearSelection, eventPayload);
}
public selectParent(clearSelection?: boolean, eventPayload?: any): void {
this.model.selectParent(clearSelection, eventPayload);
}
public setFocus(element?: any, eventPayload?: any): void {
this.model.setFocus(element, eventPayload);
}
public isFocused(element: any): boolean {
return this.model.isFocused(element);
}
public getFocus(): any {
return this.model.getFocus();
}
@@ -346,6 +294,7 @@ export class Tree implements _.ITree {
this.model.setFocus(null, eventPayload);
}
// {{SQL CARBON EDIT}} @todo anthonydresser we need to refactor our code to not need these methods
public addTraits(trait: string, elements: any[]): void {
this.model.addTraits(trait, elements);
}
@@ -354,14 +303,14 @@ export class Tree implements _.ITree {
this.model.removeTraits(trait, elements);
}
public toggleTrait(trait: string, element: any): void {
this.model.hasTrait(trait, element) ? this.model.removeTraits(trait, [element])
: this.model.addTraits(trait, [element]);
public select(element: any, eventPayload?: any): void {
this.model.select(element, eventPayload);
}
public hasTrait(trait: string, element: any): boolean {
return this.model.hasTrait(trait, element);
public deselect(element: any, eventPayload?: any): void {
this.model.deselect(element, eventPayload);
}
// {{SQL CARBON EDIT}} end
getNavigator(fromElement?: any, subTreeOnly?: boolean): INavigator<any> {
return new MappedNavigator(this.model.getNavigator(fromElement, subTreeOnly), i => i && i.getElement());
@@ -6,7 +6,6 @@
import * as Assert from 'vs/base/common/assert';
import { onUnexpectedError } from 'vs/base/common/errors';
import { IDisposable, combinedDisposable } from 'vs/base/common/lifecycle';
import * as arrays from 'vs/base/common/arrays';
import { INavigator } from 'vs/base/common/iterator';
import * as _ from './tree';
import { Event, Emitter, EventMultiplexer, Relay } from 'vs/base/common/event';
@@ -872,42 +871,6 @@ export class TreeNavigator implements INavigator<Item> {
}
}
function getRange(one: Item, other: Item): Item[] {
let oneHierarchy = one.getHierarchy();
let otherHierarchy = other.getHierarchy();
let length = arrays.commonPrefixLength(oneHierarchy, otherHierarchy);
let item: Item | null = oneHierarchy[length - 1];
let nav = item.getNavigator();
let oneIndex: number | null = null;
let otherIndex: number | null = null;
let index = 0;
let result: Item[] = [];
while (item && (oneIndex === null || otherIndex === null)) {
result.push(item);
if (item === one) {
oneIndex = index;
}
if (item === other) {
otherIndex = index;
}
index++;
item = nav.next();
}
if (oneIndex === null || otherIndex === null) {
return [];
}
let min = Math.min(oneIndex, otherIndex);
let max = Math.max(oneIndex, otherIndex);
return result.slice(min, max + 1);
}
export interface IBaseEvent {
item: Item | null;
}
@@ -1205,28 +1168,6 @@ export class TreeModel {
this.selectAll([element], eventPayload);
}
public selectRange(fromElement: any, toElement: any, eventPayload?: any): void {
let fromItem = this.getItem(fromElement);
let toItem = this.getItem(toElement);
if (!fromItem || !toItem) {
return;
}
this.selectAll(getRange(fromItem, toItem), eventPayload);
}
public deselectRange(fromElement: any, toElement: any, eventPayload?: any): void {
let fromItem = this.getItem(fromElement);
let toItem = this.getItem(toElement);
if (!fromItem || !toItem) {
return;
}
this.deselectAll(getRange(fromItem, toItem), eventPayload);
}
public selectAll(elements: any[], eventPayload?: any): void {
this.addTraits('selected', elements);
let eventData: _.ISelectionEvent = { selection: this.getSelection(), payload: eventPayload };
@@ -1249,12 +1190,6 @@ export class TreeModel {
this._onDidSelect.fire(eventData);
}
public toggleSelection(element: any, eventPayload?: any): void {
this.toggleTrait('selected', element);
let eventData: _.ISelectionEvent = { selection: this.getSelection(), payload: eventPayload };
this._onDidSelect.fire(eventData);
}
public isSelected(element: any): boolean {
let item = this.getItem(element);
@@ -1324,21 +1259,6 @@ export class TreeModel {
}
}
public selectParent(eventPayload?: any, clearSelection: boolean = true): void {
let selection = this.getSelection();
let item: Item = selection.length > 0 ? selection[0] : this.input;
let nav = this.getNavigator(item, false);
let parent = nav.parent();
if (parent) {
if (clearSelection) {
this.setSelection([parent], eventPayload);
} else {
this.select(parent, eventPayload);
}
}
}
public setFocus(element?: any, eventPayload?: any): void {
this.setTraits('focused', element ? [element] : []);
let eventData: _.IFocusEvent = { focus: this.getFocus(), payload: eventPayload };
@@ -1513,25 +1433,6 @@ export class TreeModel {
}
}
public hasTrait(trait: string, element: any): boolean {
const item = this.getItem(element);
return !!(item && item.hasTrait(trait));
}
private toggleTrait(trait: string, element: any): void {
let item = this.getItem(element);
if (!item) {
return;
}
if (item.hasTrait(trait)) {
this.removeTraits(trait, [element]);
} else {
this.addTraits(trait, [element]);
}
}
private setTraits(trait: string, elements: any[]): void {
if (elements.length === 0) {
this.removeTraits(trait, elements);
@@ -161,19 +161,19 @@ const SAMPLE: any = {
};
class TestDataSource implements _.IDataSource {
public getId(tree, element): string {
public getId(tree: _.ITree, element: any): string {
return element.id;
}
public hasChildren(tree, element): boolean {
public hasChildren(tree: _.ITree, element: any): boolean {
return !!element.children;
}
public getChildren(tree, element): Promise<any> {
public getChildren(tree: _.ITree, element: any): Promise<any> {
return Promise.resolve(element.children);
}
public getParent(tree, element): Promise<any> {
public getParent(tree: _.ITree, element: any): Promise<any> {
throw new Error('Not implemented');
}
}
@@ -700,13 +700,13 @@ suite('TreeModel - Expansion', () => {
class TestFilter implements _.IFilter {
public fn: (any) => boolean;
public fn: (element: any) => boolean;
constructor() {
this.fn = () => true;
}
public isVisible(tree, element): boolean {
public isVisible(tree: _.ITree, element: any): boolean {
return this.fn(element);
}
}
@@ -1092,39 +1092,39 @@ class DynamicModel implements _.IDataSource {
this.promiseFactory = null;
}
public addChild(parent, child): void {
public addChild(parent: string, child: string): void {
if (!this.data[parent]) {
this.data[parent] = [];
}
this.data[parent].push(child);
}
public removeChild(parent, child): void {
public removeChild(parent: string, child: string): void {
this.data[parent].splice(this.data[parent].indexOf(child), 1);
if (this.data[parent].length === 0) {
delete this.data[parent];
}
}
public move(element, oldParent, newParent): void {
public move(element: string, oldParent: string, newParent: string): void {
this.removeChild(oldParent, element);
this.addChild(newParent, element);
}
public rename(parent, oldName, newName): void {
public rename(parent: string, oldName: string, newName: string): void {
this.removeChild(parent, oldName);
this.addChild(parent, newName);
}
public getId(tree, element): string {
public getId(tree: _.ITree, element: any): string {
return element;
}
public hasChildren(tree, element): boolean {
public hasChildren(tree: _.ITree, element: any): boolean {
return !!this.data[element];
}
public getChildren(tree, element): Promise<any> {
public getChildren(tree: _.ITree, element: any): Promise<any> {
this._onGetChildren.fire(element);
const result = this.promiseFactory ? this.promiseFactory() : Promise.resolve(null);
return result.then(() => {
@@ -1133,7 +1133,7 @@ class DynamicModel implements _.IDataSource {
});
}
public getParent(tree, element): Promise<any> {
public getParent(tree: _.ITree, element: any): Promise<any> {
throw new Error('Not implemented');
}
}
@@ -1395,7 +1395,7 @@ suite('TreeModel - Dynamic data model', () => {
assert.equal(getTimes, 2);
assert.equal(gotTimes, 1);
let p2Complete;
let p2Complete: () => void;
dataModel.promiseFactory = () => { return new Promise((c) => { p2Complete = c; }); };
const p2 = model.refresh('father');
@@ -1412,7 +1412,7 @@ suite('TreeModel - Dynamic data model', () => {
assert.equal(getTimes, 3);
assert.equal(gotTimes, 2);
p2Complete();
p2Complete!();
// all good
assert.equal(refreshTimes, 5); // (+1) second son request
@@ -7,7 +7,7 @@ import * as assert from 'assert';
import { ArrayIterator } from 'vs/base/common/iterator';
import { HeightMap, IViewItem } from 'vs/base/parts/tree/browser/treeViewModel';
function makeItem(id, height): any {
function makeItem(id: any, height: any): any {
return {
id: id,
getHeight: function () { return height; },
@@ -59,7 +59,7 @@ class TestView implements IView {
}
function getSashes(splitview: SplitView): Sash[] {
return (splitview as any).sashItems.map(i => i.sash) as Sash[];
return (splitview as any).sashItems.map((i: any) => i.sash) as Sash[];
}
suite('Splitview', () => {
+3 -3
View File
@@ -143,12 +143,12 @@ suite('Paths (Node Implementation)', () => {
]
)
]);
joinTests.forEach((test) => {
joinTests.forEach((test: any[]) => {
if (!Array.isArray(test[0])) {
test[0] = [test[0]];
}
test[0].forEach((join) => {
test[1].forEach((test) => {
test[0].forEach((join: any) => {
test[1].forEach((test: any) => {
const actual = join.apply(null, test[0]);
const expected = test[1];
// For non-Windows specific tests with the Windows join(), we need to try
+7 -7
View File
@@ -176,14 +176,14 @@ suite('Types', () => {
types.validateConstraints([undefined], [types.isUndefined]);
types.validateConstraints([1], [types.isNumber]);
function foo() { }
types.validateConstraints([new foo()], [foo]);
class Foo { }
types.validateConstraints([new Foo()], [Foo]);
function isFoo(f) { }
assert.throws(() => types.validateConstraints([new foo()], [isFoo]));
function isFoo(f: any) { }
assert.throws(() => types.validateConstraints([new Foo()], [isFoo]));
function isFoo2(f) { return true; }
types.validateConstraints([new foo()], [isFoo2]);
function isFoo2(f: any) { return true; }
types.validateConstraints([new Foo()], [isFoo2]);
assert.throws(() => types.validateConstraints([1, true], [types.isNumber, types.isString]));
assert.throws(() => types.validateConstraints(['2'], [types.isNumber]));
@@ -196,7 +196,7 @@ suite('Types', () => {
assert(types.create(zeroConstructor) instanceof zeroConstructor);
assert(types.isObject(types.create(zeroConstructor)));
let manyArgConstructor = function (this: any, foo, bar) {
let manyArgConstructor = function (this: any, foo: any, bar: any) {
this.foo = foo;
this.bar = bar;
};
@@ -132,13 +132,13 @@ suite('Encoding', () => {
assert.equal(mimes.encoding, 'windows1252');
});
async function readAndDecodeFromDisk(path, _encoding) {
async function readAndDecodeFromDisk(path: string, fileEncoding: string | null) {
return new Promise<string>((resolve, reject) => {
fs.readFile(path, (err, data) => {
if (err) {
reject(err);
} else {
resolve(encoding.decode(data, _encoding));
resolve(encoding.decode(data, fileEncoding!));
}
});
});
+1 -1
View File
@@ -17,7 +17,7 @@ import { CancellationTokenSource } from 'vs/base/common/cancellation';
const ignore = () => { };
const mkdirp = (path: string, mode: number, callback: (error) => void) => {
const mkdirp = (path: string, mode: number, callback: (error: any) => void) => {
extfs.mkdirp(path, mode).then(() => callback(null), error => callback(error));
};
+6 -6
View File
@@ -431,7 +431,7 @@ suite('Glob', () => {
test('expression support (single)', function () {
let siblings = ['test.html', 'test.txt', 'test.ts', 'test.js'];
let hasSibling = name => siblings.indexOf(name) !== -1;
let hasSibling = (name: string) => siblings.indexOf(name) !== -1;
// { "**/*.js": { "when": "$(basename).ts" } }
let expression: glob.IExpression = {
@@ -467,7 +467,7 @@ suite('Glob', () => {
test('expression support (multiple)', function () {
let siblings = ['test.html', 'test.txt', 'test.ts', 'test.js'];
let hasSibling = name => siblings.indexOf(name) !== -1;
let hasSibling = (name: string) => siblings.indexOf(name) !== -1;
// { "**/*.js": { "when": "$(basename).ts" } }
let expression: glob.IExpression = {
@@ -717,7 +717,7 @@ suite('Glob', () => {
};
let siblings = ['foo.ts', 'foo.js', 'foo', 'bar'];
let hasSibling = name => siblings.indexOf(name) !== -1;
let hasSibling = (name: string) => siblings.indexOf(name) !== -1;
assert.strictEqual(glob.match(expr, 'bar', hasSibling), '**/bar');
assert.strictEqual(glob.match(expr, 'foo', hasSibling), null);
@@ -774,7 +774,7 @@ suite('Glob', () => {
let expr = { '**/*.js': { when: '$(basename).ts' } };
let siblings = ['foo.ts', 'foo.js'];
let hasSibling = name => siblings.indexOf(name) !== -1;
let hasSibling = (name: string) => siblings.indexOf(name) !== -1;
assert.strictEqual(glob.parse(expr)('bar/baz.js', 'baz.js', hasSibling), null);
assert.strictEqual(glob.parse(expr)('bar/foo.js', 'foo.js', hasSibling), '**/*.js');
@@ -818,7 +818,7 @@ suite('Glob', () => {
]);
const siblings = ['baz', 'baz.zip', 'nope'];
const hasSibling = name => siblings.indexOf(name) !== -1;
const hasSibling = (name: string) => siblings.indexOf(name) !== -1;
testOptimizationForBasenames({
'**/foo/**': { when: '$(basename).zip' },
'**/bar/**': true
@@ -924,7 +924,7 @@ suite('Glob', () => {
]);
const siblings = ['baz', 'baz.zip', 'nope'];
let hasSibling = name => siblings.indexOf(name) !== -1;
let hasSibling = (name: string) => siblings.indexOf(name) !== -1;
testOptimizationForPaths({
'**/foo/123/**': { when: '$(basename).zip' },
'**/bar/123/**': true
@@ -293,7 +293,7 @@ suite('SQLite Storage Library', () => {
return set;
}
async function testDBBasics(path, logError?: (error) => void) {
async function testDBBasics(path: string, logError?: (error: Error) => void) {
let options!: ISQLiteStorageDatabaseOptions;
if (logError) {
options = {
@@ -39,6 +39,7 @@ import { ILogService, getLogLevel } from 'vs/platform/log/common/log';
import { OcticonLabel } from 'vs/base/browser/ui/octiconLabel/octiconLabel';
import { normalizeGitHubUrl } from 'vs/code/electron-browser/issue/issueReporterUtil';
import { Button } from 'vs/base/browser/ui/button/button';
import { withUndefinedAsNull } from 'vs/base/common/types';
const MAX_URL_LENGTH = platform.isWindows ? 2081 : 5400;
@@ -211,7 +212,7 @@ export class IssueReporter extends Disposable {
styleTag.innerHTML = content.join('\n');
document.head.appendChild(styleTag);
document.body.style.color = styles.color || null;
document.body.style.color = withUndefinedAsNull(styles.color);
}
private handleExtensionData(extensions: IssueReporterExtensionData[]) {
@@ -99,7 +99,7 @@ function attachTo(item: ProcessItem) {
ipcRenderer.send('vscode:workbenchCommand', { id: 'debug.startFromConfig', from: 'processExplorer', args: [config] });
}
function getProcessIdWithHighestProperty(processList, propertyName: string) {
function getProcessIdWithHighestProperty(processList: any[], propertyName: string) {
let max = 0;
let maxProcessId;
processList.forEach(process => {
@@ -112,7 +112,7 @@ function getProcessIdWithHighestProperty(processList, propertyName: string) {
return maxProcessId;
}
function updateProcessInfo(processList): void {
function updateProcessInfo(processList: any[]): void {
const container = document.getElementById('process-list');
if (!container) {
return;
@@ -199,12 +199,12 @@ function applyZoom(zoomLevel: number): void {
browser.setZoomLevel(webFrame.getZoomLevel(), /*isTrusted*/false);
}
function showContextMenu(e) {
function showContextMenu(e: MouseEvent) {
e.preventDefault();
const items: IContextMenuItem[] = [];
const pid = parseInt(e.currentTarget.id);
const pid = parseInt((e.currentTarget as HTMLElement).id);
if (pid && typeof pid === 'number') {
items.push({
label: localize('killProcess', "Kill Process"),
@@ -277,7 +277,7 @@ export function startup(data: ProcessExplorerData): void {
applyZoom(data.zoomLevel);
// Map window process pids to titles, annotate process names with this when rendering to distinguish between them
ipcRenderer.on('vscode:windowsInfoResponse', (event, windows) => {
ipcRenderer.on('vscode:windowsInfoResponse', (_event: unknown, windows: any[]) => {
mapPidToWindowTitle = new Map<number, string>();
windows.forEach(window => mapPidToWindowTitle.set(window.pid, window.title));
});
+5 -4
View File
@@ -388,7 +388,7 @@ export class CodeApplication extends Disposable {
this.logService.info(`Tracing: waiting for windows to get ready...`);
let recordingStopped = false;
const stopRecording = (timeout) => {
const stopRecording = (timeout: boolean) => {
if (recordingStopped) {
return;
}
@@ -574,16 +574,17 @@ export class CodeApplication extends Disposable {
const hasCliArgs = hasArgs(args._);
const hasFolderURIs = hasArgs(args['folder-uri']);
const hasFileURIs = hasArgs(args['file-uri']);
const noRecentEntry = args['skip-add-to-recently-opened'] === true;
if (args['new-window'] && !hasCliArgs && !hasFolderURIs && !hasFileURIs) {
return this.windowsMainService.open({ context, cli: args, forceNewWindow: true, forceEmpty: true, initialStartup: true }); // new window if "-n" was used without paths
return this.windowsMainService.open({ context, cli: args, forceNewWindow: true, forceEmpty: true, noRecentEntry, initialStartup: true }); // new window if "-n" was used without paths
}
if (macOpenFiles && macOpenFiles.length && !hasCliArgs && !hasFolderURIs && !hasFileURIs) {
return this.windowsMainService.open({ context: OpenContext.DOCK, cli: args, urisToOpen: macOpenFiles.map(file => ({ uri: URI.file(file) })), initialStartup: true }); // mac: open-file event received on startup
return this.windowsMainService.open({ context: OpenContext.DOCK, cli: args, urisToOpen: macOpenFiles.map(file => ({ uri: URI.file(file) })), noRecentEntry, initialStartup: true }); // mac: open-file event received on startup
}
return this.windowsMainService.open({ context, cli: args, forceNewWindow: args['new-window'] || (!hasCliArgs && args['unity-launch']), diffMode: args.diff, initialStartup: true }); // default: read paths from cli
return this.windowsMainService.open({ context, cli: args, forceNewWindow: args['new-window'] || (!hasCliArgs && args['unity-launch']), diffMode: args.diff, noRecentEntry, initialStartup: true }); // default: read paths from cli
}
private afterWindowOpen(accessor: ServicesAccessor): void {
+27 -9
View File
@@ -489,7 +489,7 @@ export class WindowsManager implements IWindowsMainService {
// Remember in recent document list (unless this opens for extension development)
// Also do not add paths when files are opened for diffing, only if opened individually
if (!usedWindows.some(w => w.isExtensionDevelopmentHost) && !openConfig.diffMode && !this.environmentService.skipAddToRecentlyOpened) {
if (!usedWindows.some(w => w.isExtensionDevelopmentHost) && !openConfig.diffMode && !openConfig.noRecentEntry) {
const recents: IRecent[] = [];
for (let pathToOpen of pathsToOpen) {
if (pathToOpen.workspace) {
@@ -746,7 +746,7 @@ export class WindowsManager implements IWindowsMainService {
private doOpenFilesInExistingWindow(configuration: IOpenConfiguration, window: ICodeWindow, fileInputs?: IFileInputs): ICodeWindow {
window.focus(); // make sure window has focus
const params: { filesToOpen?, filesToCreate?, filesToDiff?, filesToWait?, termProgram?} = {};
const params: { filesToOpen?: IPath[], filesToCreate?: IPath[], filesToDiff?: IPath[], filesToWait?: IPathsToWaitFor, termProgram?: string } = {};
if (fileInputs) {
params.filesToOpen = fileInputs.filesToOpen;
params.filesToCreate = fileInputs.filesToCreate;
@@ -1216,7 +1216,7 @@ export class WindowsManager implements IWindowsMainService {
}
// Open it
this.open({ context: openConfig.context, cli: openConfig.cli, forceNewWindow: true, forceEmpty: !cliArgs.length && !folderUris.length && !fileUris.length, userEnv: openConfig.userEnv });
this.open({ context: openConfig.context, cli: openConfig.cli, forceNewWindow: true, forceEmpty: !cliArgs.length && !folderUris.length && !fileUris.length, userEnv: openConfig.userEnv, noRecentEntry: true });
}
private openInBrowserWindow(options: IOpenBrowserWindowOptions): ICodeWindow {
@@ -1897,9 +1897,15 @@ class Dialogs {
showMessageBox(options: Electron.MessageBoxOptions, window?: ICodeWindow): Promise<IMessageBoxResult> {
return this.getDialogQueue(window).queue(() => {
return new Promise(resolve => {
dialog.showMessageBox(window ? window.win : undefined!, options, (response: number, checkboxChecked: boolean) => {
const callback = (response: number, checkboxChecked: boolean) => {
resolve({ button: response, checkboxChecked });
});
};
if (window) {
dialog.showMessageBox(window.win, options, callback);
} else {
dialog.showMessageBox(options, callback);
}
});
});
}
@@ -1916,9 +1922,15 @@ class Dialogs {
return this.getDialogQueue(window).queue(() => {
return new Promise(resolve => {
dialog.showSaveDialog(window ? window.win : undefined!, options, path => {
const callback = (path: string) => {
resolve(normalizePath(path));
});
};
if (window) {
dialog.showSaveDialog(window.win, options, callback);
} else {
dialog.showSaveDialog(options, callback);
}
});
});
}
@@ -1948,9 +1960,15 @@ class Dialogs {
// Show dialog and wrap as promise
validatePathPromise.then(() => {
dialog.showOpenDialog(window ? window.win : undefined!, options, paths => {
const callback = (paths: string[]) => {
resolve(normalizePaths(paths));
});
};
if (window) {
dialog.showOpenDialog(window.win, options, callback);
} else {
dialog.showOpenDialog(options, callback);
}
});
});
});
+3 -2
View File
@@ -20,6 +20,7 @@ import { IConstructorSignature1, ServicesAccessor } from 'vs/platform/instantiat
import { IKeybindings, KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { Registry } from 'vs/platform/registry/common/platform';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { withNullAsUndefined } from 'vs/base/common/types';
export type ServicesAccessor = ServicesAccessor;
export type IEditorContributionCtor = IConstructorSignature1<ICodeEditor, IEditorContribution>;
@@ -88,7 +89,7 @@ export abstract class Command {
id: this.id,
handler: (accessor, args) => this.runCommand(accessor, args),
weight: this._kbOpts.weight,
when: kbWhen || null,
when: kbWhen,
primary: this._kbOpts.primary,
secondary: this._kbOpts.secondary,
win: this._kbOpts.win,
@@ -156,7 +157,7 @@ export abstract class EditorCommand extends Command {
return editor.invokeWithinContext((editorAccessor) => {
const kbService = editorAccessor.get(IContextKeyService);
if (!kbService.contextMatchesRules(this.precondition)) {
if (!kbService.contextMatchesRules(withNullAsUndefined(this.precondition))) {
// precondition does not hold
return;
}
@@ -272,7 +272,7 @@ class Widget {
public setPosition(position: IPosition | null | undefined, range: IRange | null | undefined, preference: ContentWidgetPositionPreference[] | null | undefined): void {
this._setPosition(position, range);
this._preference = preference || null;
this._preference = withUndefinedAsNull(preference);
this._cachedDomNodeClientWidth = -1;
this._cachedDomNodeClientHeight = -1;
}
@@ -49,6 +49,7 @@ import { ServiceCollection } from 'vs/platform/instantiation/common/serviceColle
import { INotificationService } from 'vs/platform/notification/common/notification';
import { IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService';
import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility';
import { withNullAsUndefined } from 'vs/base/common/types';
let EDITOR_ID = 0;
@@ -308,7 +309,7 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE
action.id,
action.label,
action.alias,
action.precondition,
withNullAsUndefined(action.precondition),
(): Promise<void> => {
return this._instantiationService.invokeFunction((accessor) => {
return Promise.resolve(action.runEditorCommand(accessor, this, null));
@@ -1644,6 +1645,8 @@ export class EditorModeContext extends Disposable {
private readonly _hasRenameProvider: IContextKey<boolean>;
private readonly _hasDocumentFormattingProvider: IContextKey<boolean>;
private readonly _hasDocumentSelectionFormattingProvider: IContextKey<boolean>;
private readonly _hasMultipleDocumentFormattingProvider: IContextKey<boolean>;
private readonly _hasMultipleDocumentSelectionFormattingProvider: IContextKey<boolean>;
private readonly _hasSignatureHelpProvider: IContextKey<boolean>;
private readonly _isInWalkThrough: IContextKey<boolean>;
@@ -1667,9 +1670,11 @@ export class EditorModeContext extends Disposable {
this._hasDocumentSymbolProvider = EditorContextKeys.hasDocumentSymbolProvider.bindTo(contextKeyService);
this._hasReferenceProvider = EditorContextKeys.hasReferenceProvider.bindTo(contextKeyService);
this._hasRenameProvider = EditorContextKeys.hasRenameProvider.bindTo(contextKeyService);
this._hasSignatureHelpProvider = EditorContextKeys.hasSignatureHelpProvider.bindTo(contextKeyService);
this._hasDocumentFormattingProvider = EditorContextKeys.hasDocumentFormattingProvider.bindTo(contextKeyService);
this._hasDocumentSelectionFormattingProvider = EditorContextKeys.hasDocumentSelectionFormattingProvider.bindTo(contextKeyService);
this._hasSignatureHelpProvider = EditorContextKeys.hasSignatureHelpProvider.bindTo(contextKeyService);
this._hasMultipleDocumentFormattingProvider = EditorContextKeys.hasMultipleDocumentFormattingProvider.bindTo(contextKeyService);
this._hasMultipleDocumentSelectionFormattingProvider = EditorContextKeys.hasMultipleDocumentSelectionFormattingProvider.bindTo(contextKeyService);
this._isInWalkThrough = EditorContextKeys.isInEmbeddedEditor.bindTo(contextKeyService);
const update = () => this._update();
@@ -1744,6 +1749,8 @@ export class EditorModeContext extends Disposable {
this._hasSignatureHelpProvider.set(modes.SignatureHelpProviderRegistry.has(model));
this._hasDocumentFormattingProvider.set(modes.DocumentFormattingEditProviderRegistry.has(model) || modes.DocumentRangeFormattingEditProviderRegistry.has(model));
this._hasDocumentSelectionFormattingProvider.set(modes.DocumentRangeFormattingEditProviderRegistry.has(model));
this._hasMultipleDocumentFormattingProvider.set(modes.DocumentFormattingEditProviderRegistry.all(model).length > 1 || modes.DocumentRangeFormattingEditProviderRegistry.all(model).length > 1);
this._hasMultipleDocumentSelectionFormattingProvider.set(modes.DocumentRangeFormattingEditProviderRegistry.all(model).length > 1);
this._isInWalkThrough.set(model.uri.scheme === Schemas.walkThroughSnippet);
}
}
+2 -2
View File
@@ -12,7 +12,7 @@ export class InternalEditorAction implements IEditorAction {
public readonly label: string;
public readonly alias: string;
private readonly _precondition: ContextKeyExpr | null;
private readonly _precondition: ContextKeyExpr | undefined;
private readonly _run: () => Promise<void>;
private readonly _contextKeyService: IContextKeyService;
@@ -20,7 +20,7 @@ export class InternalEditorAction implements IEditorAction {
id: string,
label: string,
alias: string,
precondition: ContextKeyExpr | null,
precondition: ContextKeyExpr | undefined,
run: () => Promise<void>,
contextKeyService: IContextKeyService
) {
+6 -1
View File
@@ -46,7 +46,12 @@ export namespace EditorContextKeys {
export const hasDocumentSymbolProvider = new RawContextKey<boolean>('editorHasDocumentSymbolProvider', false);
export const hasReferenceProvider = new RawContextKey<boolean>('editorHasReferenceProvider', false);
export const hasRenameProvider = new RawContextKey<boolean>('editorHasRenameProvider', false);
export const hasSignatureHelpProvider = new RawContextKey<boolean>('editorHasSignatureHelpProvider', false);
// -- mode context keys: formatting
export const hasDocumentFormattingProvider = new RawContextKey<boolean>('editorHasDocumentFormattingProvider', false);
export const hasDocumentSelectionFormattingProvider = new RawContextKey<boolean>('editorHasDocumentSelectionFormattingProvider', false);
export const hasSignatureHelpProvider = new RawContextKey<boolean>('editorHasSignatureHelpProvider', false);
export const hasMultipleDocumentFormattingProvider = new RawContextKey<boolean>('editorHasMultipleDocumentFormattingProvider', false);
export const hasMultipleDocumentSelectionFormattingProvider = new RawContextKey<boolean>('editorHasMultipleDocumentSelectionFormattingProvider', false);
}
+3 -2
View File
@@ -32,6 +32,7 @@ import { ignoreBracketsInToken } from 'vs/editor/common/modes/supports';
import { BracketsUtils, RichEditBracket, RichEditBrackets } from 'vs/editor/common/modes/supports/richEditBrackets';
import { IStringStream, ITextSnapshot } from 'vs/platform/files/common/files';
import { ITheme, ThemeColor } from 'vs/platform/theme/common/themeService';
import { withUndefinedAsNull } from 'vs/base/common/types';
const CHEAP_TOKENIZATION_LENGTH_LIMIT = 2048;
@@ -2877,8 +2878,8 @@ export class ModelDecorationOptions implements model.IModelDecorationOptions {
this.stickiness = options.stickiness || model.TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges;
this.zIndex = options.zIndex || 0;
this.className = options.className ? cleanClassName(options.className) : null;
this.hoverMessage = options.hoverMessage || null;
this.glyphMarginHoverMessage = options.glyphMarginHoverMessage || null;
this.hoverMessage = withUndefinedAsNull(options.hoverMessage);
this.glyphMarginHoverMessage = withUndefinedAsNull(options.glyphMarginHoverMessage);
this.isWholeLine = options.isWholeLine || false;
this.showIfCollapsed = options.showIfCollapsed || false;
this.collapseOnReplaceEdit = options.collapseOnReplaceEdit || false;
+22 -2
View File
@@ -929,6 +929,8 @@ export interface DocumentFormattingEditProvider {
*/
readonly extensionId?: ExtensionIdentifier;
readonly displayName?: string;
/**
* Provide formatting edits for a whole document.
*/
@@ -939,13 +941,13 @@ export interface DocumentFormattingEditProvider {
* the formatting-feature.
*/
export interface DocumentRangeFormattingEditProvider {
/**
* @internal
*/
readonly extensionId?: ExtensionIdentifier;
readonly displayName?: string;
/**
* Provide formatting edits for a range in a document.
*
@@ -1396,6 +1398,24 @@ export interface WorkspaceCommentProvider {
onDidChangeCommentThreads(): Event<CommentThreadChangedEvent>;
}
/**
* @internal
*/
export interface IWebviewOptions {
readonly enableScripts?: boolean;
readonly enableCommandUris?: boolean;
readonly localResourceRoots?: ReadonlyArray<URI>;
readonly portMapping?: ReadonlyArray<{ port: number, resolvedPort: number }>;
}
/**
* @internal
*/
export interface IWebviewPanelOptions {
readonly enableFindWidget?: boolean;
readonly retainContextWhenHidden?: boolean;
}
export interface ICodeLensSymbol {
range: IRange;
id?: string;
@@ -26,7 +26,7 @@ export interface IEditorWorkerService {
canComputeDirtyDiff(original: URI, modified: URI): boolean;
computeDirtyDiff(original: URI, modified: URI, ignoreTrimWhitespace: boolean): Promise<IChange[] | null>;
computeMoreMinimalEdits(resource: URI, edits: TextEdit[] | null | undefined): Promise<TextEdit[] | null | undefined>;
computeMoreMinimalEdits(resource: URI, edits: TextEdit[] | null | undefined): Promise<TextEdit[] | undefined>;
canComputeWordRanges(resource: URI): boolean;
computeWordRanges(resource: URI, range: IRange): Promise<{ [word: string]: IRange[] } | null>;
@@ -20,6 +20,7 @@ import { IDiffComputationResult, IEditorWorkerService } from 'vs/editor/common/s
import { IModelService } from 'vs/editor/common/services/modelService';
import { ITextResourceConfigurationService } from 'vs/editor/common/services/resourceConfiguration';
import { regExpFlags } from 'vs/base/common/strings';
import { isNonEmptyArray } from 'vs/base/common/arrays';
/**
* Stop syncing a model to the worker if it was not needed for 1 min.
@@ -88,14 +89,15 @@ export class EditorWorkerServiceImpl extends Disposable implements IEditorWorker
return this._workerManager.withWorker().then(client => client.computeDirtyDiff(original, modified, ignoreTrimWhitespace));
}
public computeMoreMinimalEdits(resource: URI, edits: modes.TextEdit[] | null | undefined): Promise<modes.TextEdit[] | null | undefined> {
if (!Array.isArray(edits) || edits.length === 0) {
return Promise.resolve(edits);
} else {
public computeMoreMinimalEdits(resource: URI, edits: modes.TextEdit[] | null | undefined): Promise<modes.TextEdit[] | undefined> {
if (isNonEmptyArray(edits)) {
if (!canSyncModel(this._modelService, resource)) {
return Promise.resolve(edits); // File too large
}
return this._workerManager.withWorker().then(client => client.computeMoreMinimalEdits(resource, edits));
} else {
return Promise.resolve(undefined);
}
}
@@ -15,6 +15,7 @@ import { NULL_LANGUAGE_IDENTIFIER, NULL_MODE_ID } from 'vs/editor/common/modes/n
import { ILanguageExtensionPoint } from 'vs/editor/common/services/modeService';
import { Extensions, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry';
import { Registry } from 'vs/platform/registry/common/platform';
import { withUndefinedAsNull } from 'vs/base/common/types';
const hasOwnProperty = Object.prototype.hasOwnProperty;
@@ -267,7 +268,7 @@ export class LanguagesRegistry extends Disposable {
return null;
}
const language = this._languages[modeId];
return (language.mimetypes[0] || null);
return withUndefinedAsNull(language.mimetypes[0]);
}
public extractModeIds(commaSeparatedMimetypesOrCommaSeparatedIds: string | undefined): string[] {
@@ -16,6 +16,7 @@ import { keys } from 'vs/base/common/map';
import { IMarkerDecorationsService } from 'vs/editor/common/services/markersDecorationService';
import { Schemas } from 'vs/base/common/network';
import { Emitter, Event } from 'vs/base/common/event';
import { withUndefinedAsNull } from 'vs/base/common/types';
function MODEL_ID(resource: URI): string {
return resource.toString();
@@ -80,7 +81,7 @@ export class MarkerDecorationsService extends Disposable implements IMarkerDecor
getMarker(model: ITextModel, decoration: IModelDecoration): IMarker | null {
const markerDecorations = this._markerDecorations.get(MODEL_ID(model.uri));
return markerDecorations ? markerDecorations.getMarker(decoration) || null : null;
return markerDecorations ? withUndefinedAsNull(markerDecorations.getMarker(decoration)) : null;
}
getLiveMarkers(model: ITextModel): [Range, IMarker][] {
@@ -163,7 +163,7 @@ export class LightBulbWidget extends Disposable implements IContentWidget {
const lineContent = model.getLineContent(lineNumber);
const indent = TextModel.computeIndentLevel(lineContent, tabSize);
const lineHasSpace = config.fontInfo.spaceWidth * indent > 22;
const isFolded = (lineNumber) => {
const isFolded = (lineNumber: number) => {
return lineNumber > 2 && this._editor.getTopForLineNumber(lineNumber) === this._editor.getTopForLineNumber(lineNumber - 1);
};
@@ -25,7 +25,7 @@ class CodeLensViewZone implements editorBrowser.IViewZone {
afterLineNumber: number;
private _lastHeight: number;
private _lastHeight?: number;
private readonly _onHeight: Function;
constructor(afterLineNumber: number, onHeight: Function) {
@@ -67,7 +67,7 @@ suite('FindController', () => {
getBoolean: (key: string) => !!queryState[key],
getNumber: (key: string) => undefined,
store: (key: string, value: any) => { queryState[key] = value; return Promise.resolve(); },
remove: (key) => undefined
remove: () => undefined
} as any);
if (platform.isMacintosh) {
@@ -442,7 +442,7 @@ suite('FindController query options persistence', () => {
getBoolean: (key: string) => !!queryState[key],
getNumber: (key: string) => undefined,
store: (key: string, value: any) => { queryState[key] = value; return Promise.resolve(); },
remove: (key) => undefined
remove: () => undefined
} as any);
test('matchCase', () => {
@@ -66,7 +66,7 @@ export class FoldingModel {
public update(newRegions: FoldingRegions, blockedLineNumers: number[] = []): void {
let newEditorDecorations: IModelDeltaDecoration[] = [];
let isBlocked = (startLineNumber, endLineNumber) => {
let isBlocked = (startLineNumber: number, endLineNumber: number) => {
for (let blockedLineNumber of blockedLineNumers) {
if (startLineNumber < blockedLineNumber && blockedLineNumber <= endLineNumber) { // first line is visible
return true;
+223 -118
View File
@@ -3,138 +3,258 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { alert } from 'vs/base/browser/ui/aria/aria';
import { isNonEmptyArray } from 'vs/base/common/arrays';
import { CancellationToken } from 'vs/base/common/cancellation';
import { illegalArgument, onUnexpectedExternalError } from 'vs/base/common/errors';
import { URI } from 'vs/base/common/uri';
import { isNonEmptyArray } from 'vs/base/common/arrays';
import { Range } from 'vs/editor/common/core/range';
import { ITextModel } from 'vs/editor/common/model';
import { registerLanguageCommand } from 'vs/editor/browser/editorExtensions';
import { DocumentFormattingEditProviderRegistry, DocumentRangeFormattingEditProviderRegistry, OnTypeFormattingEditProviderRegistry, FormattingOptions, TextEdit } from 'vs/editor/common/modes';
import { IModelService } from 'vs/editor/common/services/modelService';
import { first } from 'vs/base/common/async';
import { CodeEditorStateFlag, EditorState } from 'vs/editor/browser/core/editorState';
import { IActiveCodeEditor, isCodeEditor } from 'vs/editor/browser/editorBrowser';
import { registerLanguageCommand, ServicesAccessor } from 'vs/editor/browser/editorExtensions';
import { Position } from 'vs/editor/common/core/position';
import { CancellationToken } from 'vs/base/common/cancellation';
import { Range } from 'vs/editor/common/core/range';
import { Selection } from 'vs/editor/common/core/selection';
import * as editorCommon from 'vs/editor/common/editorCommon';
import { ISingleEditOperation, ITextModel } from 'vs/editor/common/model';
import { DocumentFormattingEditProvider, DocumentFormattingEditProviderRegistry, DocumentRangeFormattingEditProvider, DocumentRangeFormattingEditProviderRegistry, FormattingOptions, OnTypeFormattingEditProviderRegistry, TextEdit } from 'vs/editor/common/modes';
import { IEditorWorkerService } from 'vs/editor/common/services/editorWorkerService';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IModelService } from 'vs/editor/common/services/modelService';
import { FormattingEdit } from 'vs/editor/contrib/format/formattingEdit';
import * as nls from 'vs/nls';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import { IDisposable } from 'vs/base/common/lifecycle';
export const enum FormatMode {
Auto = 1,
Manual = 2,
}
export function alertFormattingEdits(edits: ISingleEditOperation[]): void {
export const enum FormatKind {
Document = 8,
Range = 16,
OnType = 32,
}
edits = edits.filter(edit => edit.range);
if (!edits.length) {
return;
}
export interface IFormatterConflictCallback {
(extensionIds: (ExtensionIdentifier | undefined)[], model: ITextModel, mode: number): void;
}
let _conflictResolver: IFormatterConflictCallback | undefined;
export function setFormatterConflictCallback(callback: IFormatterConflictCallback): IDisposable {
let oldCallback = _conflictResolver;
_conflictResolver = callback;
return {
dispose() {
if (oldCallback) {
_conflictResolver = oldCallback;
oldCallback = undefined;
}
let { range } = edits[0];
for (let i = 1; i < edits.length; i++) {
range = Range.plusRange(range, edits[i].range);
}
const { startLineNumber, endLineNumber } = range;
if (startLineNumber === endLineNumber) {
if (edits.length === 1) {
alert(nls.localize('hint11', "Made 1 formatting edit on line {0}", startLineNumber));
} else {
alert(nls.localize('hintn1', "Made {0} formatting edits on line {1}", edits.length, startLineNumber));
}
} else {
if (edits.length === 1) {
alert(nls.localize('hint1n', "Made 1 formatting edit between lines {0} and {1}", startLineNumber, endLineNumber));
} else {
alert(nls.localize('hintnn', "Made {0} formatting edits between lines {1} and {2}", edits.length, startLineNumber, endLineNumber));
}
};
}
function invokeFormatterCallback<T extends { extensionId?: ExtensionIdentifier }>(formatter: T[], model: ITextModel, mode: number): void {
if (_conflictResolver) {
const ids = formatter.map(formatter => formatter.extensionId);
_conflictResolver(ids, model, mode);
}
}
export async function getDocumentRangeFormattingEdits(
telemetryService: ITelemetryService,
export function getRealAndSyntheticDocumentFormattersOrdered(model: ITextModel): DocumentFormattingEditProvider[] {
const result: DocumentFormattingEditProvider[] = [];
const seen = new Set<string>();
// (1) add all document formatter
const docFormatter = DocumentFormattingEditProviderRegistry.ordered(model);
for (const formatter of docFormatter) {
result.push(formatter);
if (formatter.extensionId) {
seen.add(ExtensionIdentifier.toKey(formatter.extensionId));
}
}
// (2) add all range formatter as document formatter (unless the same extension already did that)
const rangeFormatter = DocumentRangeFormattingEditProviderRegistry.ordered(model);
for (const formatter of rangeFormatter) {
if (formatter.extensionId) {
if (seen.has(ExtensionIdentifier.toKey(formatter.extensionId))) {
continue;
}
seen.add(ExtensionIdentifier.toKey(formatter.extensionId));
}
result.push({
displayName: formatter.displayName,
extensionId: formatter.extensionId,
provideDocumentFormattingEdits(model, options, token) {
return formatter.provideDocumentRangeFormattingEdits(model, model.getFullModelRange(), options, token);
}
});
}
return result;
}
export async function formatDocumentRangeWithProvider(
accessor: ServicesAccessor,
provider: DocumentRangeFormattingEditProvider,
editorOrModel: ITextModel | IActiveCodeEditor,
range: Range,
token: CancellationToken
): Promise<boolean> {
const workerService = accessor.get(IEditorWorkerService);
let model: ITextModel;
let validate: () => boolean;
if (isCodeEditor(editorOrModel)) {
model = editorOrModel.getModel();
const state = new EditorState(editorOrModel, CodeEditorStateFlag.Value | CodeEditorStateFlag.Position);
validate = () => state.validate(editorOrModel);
} else {
model = editorOrModel;
const versionNow = editorOrModel.getVersionId();
validate = () => versionNow === editorOrModel.getVersionId();
}
const rawEdits = await provider.provideDocumentRangeFormattingEdits(
model,
range,
model.getFormattingOptions(),
token
);
const edits = await workerService.computeMoreMinimalEdits(model.uri, rawEdits);
if (!validate()) {
return true;
}
if (!edits || edits.length === 0) {
return false;
}
if (isCodeEditor(editorOrModel)) {
// use editor to apply edits
FormattingEdit.execute(editorOrModel, edits);
alertFormattingEdits(edits);
editorOrModel.pushUndoStop();
editorOrModel.focus();
editorOrModel.revealPositionInCenterIfOutsideViewport(editorOrModel.getPosition(), editorCommon.ScrollType.Immediate);
} else {
// use model to apply edits
const [{ range }] = edits;
const initialSelection = new Selection(range.startLineNumber, range.startColumn, range.endLineNumber, range.endColumn);
model.pushEditOperations([initialSelection], edits.map(edit => {
return {
text: edit.text,
range: Range.lift(edit.range),
forceMoveMarkers: true
};
}), undoEdits => {
for (const { range } of undoEdits) {
if (Range.areIntersectingOrTouching(range, initialSelection)) {
return [new Selection(range.startLineNumber, range.startColumn, range.endLineNumber, range.endColumn)];
}
}
return null;
});
}
return true;
}
export async function formatDocumentWithProvider(
accessor: ServicesAccessor,
provider: DocumentFormattingEditProvider,
editorOrModel: ITextModel | IActiveCodeEditor,
token: CancellationToken
): Promise<boolean> {
const workerService = accessor.get(IEditorWorkerService);
let model: ITextModel;
let validate: () => boolean;
if (isCodeEditor(editorOrModel)) {
model = editorOrModel.getModel();
const state = new EditorState(editorOrModel, CodeEditorStateFlag.Value | CodeEditorStateFlag.Position);
validate = () => state.validate(editorOrModel);
} else {
model = editorOrModel;
const versionNow = editorOrModel.getVersionId();
validate = () => versionNow === editorOrModel.getVersionId();
}
const rawEdits = await provider.provideDocumentFormattingEdits(
model,
model.getFormattingOptions(),
token
);
const edits = await workerService.computeMoreMinimalEdits(model.uri, rawEdits);
if (!validate()) {
return true;
}
if (!edits || edits.length === 0) {
return false;
}
if (isCodeEditor(editorOrModel)) {
// use editor to apply edits
FormattingEdit.execute(editorOrModel, edits);
alertFormattingEdits(edits);
editorOrModel.pushUndoStop();
editorOrModel.focus();
editorOrModel.revealPositionInCenterIfOutsideViewport(editorOrModel.getPosition(), editorCommon.ScrollType.Immediate);
} else {
// use model to apply edits
const [{ range }] = edits;
const initialSelection = new Selection(range.startLineNumber, range.startColumn, range.endLineNumber, range.endColumn);
model.pushEditOperations([initialSelection], edits.map(edit => {
return {
text: edit.text,
range: Range.lift(edit.range),
forceMoveMarkers: true
};
}), undoEdits => {
for (const { range } of undoEdits) {
if (Range.areIntersectingOrTouching(range, initialSelection)) {
return [new Selection(range.startLineNumber, range.startColumn, range.endLineNumber, range.endColumn)];
}
}
return null;
});
}
return true;
}
export async function getDocumentRangeFormattingEditsUntilResult(
workerService: IEditorWorkerService,
model: ITextModel,
range: Range,
options: FormattingOptions,
mode: FormatMode,
token: CancellationToken
): Promise<TextEdit[] | undefined | null> {
): Promise<TextEdit[] | undefined> {
const providers = DocumentRangeFormattingEditProviderRegistry.ordered(model);
/* __GDPR__
"formatterInfo" : {
"type" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"language" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"count" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"extensions" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
for (const provider of providers) {
let rawEdits = await Promise.resolve(provider.provideDocumentRangeFormattingEdits(model, range, options, token)).catch(onUnexpectedExternalError);
if (isNonEmptyArray(rawEdits)) {
return await workerService.computeMoreMinimalEdits(model.uri, rawEdits);
}
*/
telemetryService.publicLog('formatterInfo', {
type: 'range',
language: model.getLanguageIdentifier().language,
count: providers.length,
extensions: providers.map(p => p.extensionId ? ExtensionIdentifier.toKey(p.extensionId) : 'unknown')
});
invokeFormatterCallback(providers, model, mode | FormatKind.Range);
return first(providers.map(provider => () => {
return Promise.resolve(provider.provideDocumentRangeFormattingEdits(model, range, options, token)).catch(onUnexpectedExternalError);
}), isNonEmptyArray).then(edits => {
// break edits into smaller edits
return workerService.computeMoreMinimalEdits(model.uri, edits);
});
}
return undefined;
}
export function getDocumentFormattingEdits(
telemetryService: ITelemetryService,
export async function getDocumentFormattingEditsUntilResult(
workerService: IEditorWorkerService,
model: ITextModel,
options: FormattingOptions,
mode: FormatMode,
token: CancellationToken
): Promise<TextEdit[] | null | undefined> {
): Promise<TextEdit[] | undefined> {
const docFormattingProviders = DocumentFormattingEditProviderRegistry.ordered(model);
/* __GDPR__
"formatterInfo" : {
"type" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"language" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"count" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"extensions" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
const providers = getRealAndSyntheticDocumentFormattersOrdered(model);
for (const provider of providers) {
let rawEdits = await Promise.resolve(provider.provideDocumentFormattingEdits(model, options, token)).catch(onUnexpectedExternalError);
if (isNonEmptyArray(rawEdits)) {
return await workerService.computeMoreMinimalEdits(model.uri, rawEdits);
}
*/
telemetryService.publicLog('formatterInfo', {
type: 'document',
language: model.getLanguageIdentifier().language,
count: docFormattingProviders.length,
extensions: docFormattingProviders.map(p => p.extensionId ? ExtensionIdentifier.toKey(p.extensionId) : 'unknown')
});
if (docFormattingProviders.length > 0) {
return first(docFormattingProviders.map(provider => () => {
// first with result wins...
return Promise.resolve(provider.provideDocumentFormattingEdits(model, options, token)).catch(onUnexpectedExternalError);
}), isNonEmptyArray).then(edits => {
// break edits into smaller edits
return workerService.computeMoreMinimalEdits(model.uri, edits);
});
} else {
// try range formatters when no document formatter is registered
return getDocumentRangeFormattingEdits(telemetryService, workerService, model, model.getFullModelRange(), options, mode | FormatKind.Document, token);
}
return undefined;
}
export function getOnTypeFormattingEdits(
telemetryService: ITelemetryService,
workerService: IEditorWorkerService,
model: ITextModel,
position: Position,
@@ -144,21 +264,6 @@ export function getOnTypeFormattingEdits(
const providers = OnTypeFormattingEditProviderRegistry.ordered(model);
/* __GDPR__
"formatterInfo" : {
"type" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"language" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"count" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"extensions" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
}
*/
telemetryService.publicLog('formatterInfo', {
type: 'ontype',
language: model.getLanguageIdentifier().language,
count: providers.length,
extensions: providers.map(p => p.extensionId ? ExtensionIdentifier.toKey(p.extensionId) : 'unknown')
});
if (providers.length === 0) {
return Promise.resolve(undefined);
}
@@ -181,7 +286,7 @@ registerLanguageCommand('_executeFormatRangeProvider', function (accessor, args)
if (!model) {
throw illegalArgument('resource');
}
return getDocumentRangeFormattingEdits(accessor.get(ITelemetryService), accessor.get(IEditorWorkerService), model, Range.lift(range), options, FormatMode.Auto, CancellationToken.None);
return getDocumentRangeFormattingEditsUntilResult(accessor.get(IEditorWorkerService), model, Range.lift(range), options, CancellationToken.None);
});
registerLanguageCommand('_executeFormatDocumentProvider', function (accessor, args) {
@@ -194,7 +299,7 @@ registerLanguageCommand('_executeFormatDocumentProvider', function (accessor, ar
throw illegalArgument('resource');
}
return getDocumentFormattingEdits(accessor.get(ITelemetryService), accessor.get(IEditorWorkerService), model, options, FormatMode.Auto, CancellationToken.None);
return getDocumentFormattingEditsUntilResult(accessor.get(IEditorWorkerService), model, options, CancellationToken.None);
});
registerLanguageCommand('_executeFormatOnTypeProvider', function (accessor, args) {
@@ -207,5 +312,5 @@ registerLanguageCommand('_executeFormatOnTypeProvider', function (accessor, args
throw illegalArgument('resource');
}
return getOnTypeFormattingEdits(accessor.get(ITelemetryService), accessor.get(IEditorWorkerService), model, Position.lift(position), ch, options);
return getOnTypeFormattingEdits(accessor.get(IEditorWorkerService), model, Position.lift(position), ch, options);
});
+80 -174
View File
@@ -3,122 +3,27 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { alert } from 'vs/base/browser/ui/aria/aria';
import { isNonEmptyArray } from 'vs/base/common/arrays';
import { CancellationToken } from 'vs/base/common/cancellation';
import { KeyChord, KeyCode, KeyMod } from 'vs/base/common/keyCodes';
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
import { CodeEditorStateFlag, EditorState } from 'vs/editor/browser/core/editorState';
import { IActiveCodeEditor, ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { EditorAction, registerEditorAction, registerEditorContribution, ServicesAccessor } from 'vs/editor/browser/editorExtensions';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
import { CharacterSet } from 'vs/editor/common/core/characterClassifier';
import { Range } from 'vs/editor/common/core/range';
import * as editorCommon from 'vs/editor/common/editorCommon';
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
import { ISingleEditOperation } from 'vs/editor/common/model';
import { DocumentRangeFormattingEditProviderRegistry, FormattingOptions, OnTypeFormattingEditProviderRegistry } from 'vs/editor/common/modes';
import { DocumentRangeFormattingEditProviderRegistry, OnTypeFormattingEditProviderRegistry } from 'vs/editor/common/modes';
import { IEditorWorkerService } from 'vs/editor/common/services/editorWorkerService';
import { getOnTypeFormattingEdits, getDocumentFormattingEdits, getDocumentRangeFormattingEdits, FormatMode } from 'vs/editor/contrib/format/format';
import { getOnTypeFormattingEdits, formatDocumentWithProvider, formatDocumentRangeWithProvider, alertFormattingEdits, getRealAndSyntheticDocumentFormattersOrdered } from 'vs/editor/contrib/format/format';
import { FormattingEdit } from 'vs/editor/contrib/format/formattingEdit';
import * as nls from 'vs/nls';
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
import { CommandsRegistry, ICommandService } from 'vs/platform/commands/common/commands';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
function alertFormattingEdits(edits: ISingleEditOperation[]): void {
edits = edits.filter(edit => edit.range);
if (!edits.length) {
return;
}
let { range } = edits[0];
for (let i = 1; i < edits.length; i++) {
range = Range.plusRange(range, edits[i].range);
}
const { startLineNumber, endLineNumber } = range;
if (startLineNumber === endLineNumber) {
if (edits.length === 1) {
alert(nls.localize('hint11', "Made 1 formatting edit on line {0}", startLineNumber));
} else {
alert(nls.localize('hintn1', "Made {0} formatting edits on line {1}", edits.length, startLineNumber));
}
} else {
if (edits.length === 1) {
alert(nls.localize('hint1n', "Made 1 formatting edit between lines {0} and {1}", startLineNumber, endLineNumber));
} else {
alert(nls.localize('hintnn', "Made {0} formatting edits between lines {1} and {2}", edits.length, startLineNumber, endLineNumber));
}
}
}
const enum FormatRangeType {
Full,
Selection,
}
function formatDocumentRange(
telemetryService: ITelemetryService,
workerService: IEditorWorkerService,
editor: IActiveCodeEditor,
rangeOrRangeType: Range | FormatRangeType,
options: FormattingOptions,
token: CancellationToken
): Promise<void> {
const state = new EditorState(editor, CodeEditorStateFlag.Value | CodeEditorStateFlag.Position);
const model = editor.getModel();
let range: Range;
if (rangeOrRangeType === FormatRangeType.Full) {
// full
range = model.getFullModelRange();
} else if (rangeOrRangeType === FormatRangeType.Selection) {
// selection or line (when empty)
range = editor.getSelection();
if (range.isEmpty()) {
range = new Range(range.startLineNumber, 1, range.endLineNumber, model.getLineMaxColumn(range.endLineNumber));
}
} else {
// as is
range = rangeOrRangeType;
}
return getDocumentRangeFormattingEdits(telemetryService, workerService, model, range, options, FormatMode.Manual, token).then(edits => {
// make edit only when the editor didn't change while
// computing and only when there are edits
if (state.validate(editor) && isNonEmptyArray(edits)) {
FormattingEdit.execute(editor, edits);
alertFormattingEdits(edits);
editor.focus();
editor.revealPositionInCenterIfOutsideViewport(editor.getPosition(), editorCommon.ScrollType.Immediate);
}
});
}
function formatDocument(telemetryService: ITelemetryService, workerService: IEditorWorkerService, editor: IActiveCodeEditor, options: FormattingOptions, token: CancellationToken): Promise<void> {
const allEdits: ISingleEditOperation[] = [];
const state = new EditorState(editor, CodeEditorStateFlag.Value | CodeEditorStateFlag.Position);
return getDocumentFormattingEdits(telemetryService, workerService, editor.getModel(), options, FormatMode.Manual, token).then(edits => {
// make edit only when the editor didn't change while
// computing and only when there are edits
if (state.validate(editor) && isNonEmptyArray(edits)) {
FormattingEdit.execute(editor, edits);
alertFormattingEdits(allEdits);
editor.pushUndoStop();
editor.focus();
editor.revealPositionInCenterIfOutsideViewport(editor.getPosition(), editorCommon.ScrollType.Immediate);
}
});
}
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { onUnexpectedError } from 'vs/base/common/errors';
class FormatOnType implements editorCommon.IEditorContribution {
@@ -130,17 +35,25 @@ class FormatOnType implements editorCommon.IEditorContribution {
constructor(
editor: ICodeEditor,
@ITelemetryService private readonly _telemetryService: ITelemetryService,
@IEditorWorkerService private readonly _workerService: IEditorWorkerService
) {
this._editor = editor;
this._callOnDispose.push(editor.onDidChangeConfiguration(() => this.update()));
this._callOnDispose.push(editor.onDidChangeModel(() => this.update()));
this._callOnDispose.push(editor.onDidChangeModelLanguage(() => this.update()));
this._callOnDispose.push(OnTypeFormattingEditProviderRegistry.onDidChange(this.update, this));
this._callOnDispose.push(editor.onDidChangeConfiguration(() => this._update()));
this._callOnDispose.push(editor.onDidChangeModel(() => this._update()));
this._callOnDispose.push(editor.onDidChangeModelLanguage(() => this._update()));
this._callOnDispose.push(OnTypeFormattingEditProviderRegistry.onDidChange(this._update, this));
}
private update(): void {
getId(): string {
return FormatOnType.ID;
}
dispose(): void {
this._callOnDispose = dispose(this._callOnDispose);
this._callOnModel = dispose(this._callOnModel);
}
private _update(): void {
// clean up
this._callOnModel = dispose(this._callOnModel);
@@ -171,12 +84,12 @@ class FormatOnType implements editorCommon.IEditorContribution {
this._callOnModel.push(this._editor.onDidType((text: string) => {
let lastCharCode = text.charCodeAt(text.length - 1);
if (triggerChars.has(lastCharCode)) {
this.trigger(String.fromCharCode(lastCharCode));
this._trigger(String.fromCharCode(lastCharCode));
}
}));
}
private trigger(ch: string): void {
private _trigger(ch: string): void {
if (!this._editor.hasModel()) {
return;
}
@@ -214,7 +127,6 @@ class FormatOnType implements editorCommon.IEditorContribution {
});
getOnTypeFormattingEdits(
this._telemetryService,
this._workerService,
model,
position,
@@ -238,42 +150,41 @@ class FormatOnType implements editorCommon.IEditorContribution {
throw err;
});
}
public getId(): string {
return FormatOnType.ID;
}
public dispose(): void {
this._callOnDispose = dispose(this._callOnDispose);
this._callOnModel = dispose(this._callOnModel);
}
}
class FormatOnPaste implements editorCommon.IEditorContribution {
private static readonly ID = 'editor.contrib.formatOnPaste';
private callOnDispose: IDisposable[];
private callOnModel: IDisposable[];
private _callOnDispose: IDisposable[];
private _callOnModel: IDisposable[];
constructor(
private readonly editor: ICodeEditor,
@IEditorWorkerService private readonly workerService: IEditorWorkerService,
@ITelemetryService private readonly telemetryService: ITelemetryService,
@IInstantiationService private readonly _instantiationService: IInstantiationService,
) {
this.callOnDispose = [];
this.callOnModel = [];
this._callOnDispose = [];
this._callOnModel = [];
this.callOnDispose.push(editor.onDidChangeConfiguration(() => this.update()));
this.callOnDispose.push(editor.onDidChangeModel(() => this.update()));
this.callOnDispose.push(editor.onDidChangeModelLanguage(() => this.update()));
this.callOnDispose.push(DocumentRangeFormattingEditProviderRegistry.onDidChange(this.update, this));
this._callOnDispose.push(editor.onDidChangeConfiguration(() => this._update()));
this._callOnDispose.push(editor.onDidChangeModel(() => this._update()));
this._callOnDispose.push(editor.onDidChangeModelLanguage(() => this._update()));
this._callOnDispose.push(DocumentRangeFormattingEditProviderRegistry.onDidChange(this._update, this));
}
private update(): void {
getId(): string {
return FormatOnPaste.ID;
}
dispose(): void {
this._callOnDispose = dispose(this._callOnDispose);
this._callOnModel = dispose(this._callOnModel);
}
private _update(): void {
// clean up
this.callOnModel = dispose(this.callOnModel);
this._callOnModel = dispose(this._callOnModel);
// we are disabled
if (!this.editor.getConfiguration().contribInfo.formatOnPaste) {
@@ -285,53 +196,41 @@ class FormatOnPaste implements editorCommon.IEditorContribution {
return;
}
let model = this.editor.getModel();
// no support
if (!DocumentRangeFormattingEditProviderRegistry.has(model)) {
// no formatter
if (!DocumentRangeFormattingEditProviderRegistry.has(this.editor.getModel())) {
return;
}
this.callOnModel.push(this.editor.onDidPaste((range: Range) => {
this.trigger(range);
}));
this._callOnModel.push(this.editor.onDidPaste(range => this._trigger(range)));
}
private trigger(range: Range): void {
private _trigger(range: Range): void {
if (!this.editor.hasModel()) {
return;
}
if (this.editor.getSelections().length > 1) {
return;
}
const model = this.editor.getModel();
formatDocumentRange(this.telemetryService, this.workerService, this.editor, range, model.getFormattingOptions(), CancellationToken.None);
}
public getId(): string {
return FormatOnPaste.ID;
}
public dispose(): void {
this.callOnDispose = dispose(this.callOnDispose);
this.callOnModel = dispose(this.callOnModel);
const provider = DocumentRangeFormattingEditProviderRegistry.ordered(this.editor.getModel());
if (provider.length !== 1) {
// print status in n>1 case?
return;
}
this._instantiationService.invokeFunction(formatDocumentRangeWithProvider, provider[0], this.editor, range, CancellationToken.None).catch(onUnexpectedError);
}
}
export class FormatDocumentAction extends EditorAction {
class FormatDocumentAction extends EditorAction {
constructor() {
super({
id: 'editor.action.formatDocument',
label: nls.localize('formatDocument.label', "Format Document"),
alias: 'Format Document',
precondition: EditorContextKeys.writable,
precondition: ContextKeyExpr.and(EditorContextKeys.writable, EditorContextKeys.hasDocumentFormattingProvider, EditorContextKeys.hasMultipleDocumentFormattingProvider.toNegated()),
kbOpts: {
kbExpr: EditorContextKeys.editorTextFocus,
kbExpr: ContextKeyExpr.and(EditorContextKeys.editorTextFocus, EditorContextKeys.hasDocumentFormattingProvider),
primary: KeyMod.Shift | KeyMod.Alt | KeyCode.KEY_F,
// secondary: [KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_D)],
linux: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_I },
weight: KeybindingWeight.EditorContrib
},
@@ -343,26 +242,29 @@ export class FormatDocumentAction extends EditorAction {
});
}
run(accessor: ServicesAccessor, editor: ICodeEditor): Promise<void> | void {
async run(accessor: ServicesAccessor, editor: ICodeEditor): Promise<void> {
if (!editor.hasModel()) {
return;
}
const workerService = accessor.get(IEditorWorkerService);
const telemetryService = accessor.get(ITelemetryService);
return formatDocument(telemetryService, workerService, editor, editor.getModel().getFormattingOptions(), CancellationToken.None);
const instaService = accessor.get(IInstantiationService);
const model = editor.getModel();
const [provider] = getRealAndSyntheticDocumentFormattersOrdered(model);
if (provider) {
await instaService.invokeFunction(formatDocumentWithProvider, provider, editor, CancellationToken.None);
}
}
}
export class FormatSelectionAction extends EditorAction {
class FormatSelectionAction extends EditorAction {
constructor() {
super({
id: 'editor.action.formatSelection',
label: nls.localize('formatSelection.label', "Format Selection"),
alias: 'Format Code',
precondition: ContextKeyExpr.and(EditorContextKeys.writable),
precondition: ContextKeyExpr.and(EditorContextKeys.writable, EditorContextKeys.hasDocumentSelectionFormattingProvider, EditorContextKeys.hasMultipleDocumentSelectionFormattingProvider.toNegated()),
kbOpts: {
kbExpr: EditorContextKeys.editorTextFocus,
kbExpr: ContextKeyExpr.and(EditorContextKeys.editorTextFocus, EditorContextKeys.hasDocumentSelectionFormattingProvider),
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_F),
weight: KeybindingWeight.EditorContrib
},
@@ -374,13 +276,19 @@ export class FormatSelectionAction extends EditorAction {
});
}
run(accessor: ServicesAccessor, editor: ICodeEditor): Promise<void> | void {
async run(accessor: ServicesAccessor, editor: ICodeEditor): Promise<void> {
if (!editor.hasModel()) {
return;
}
const workerService = accessor.get(IEditorWorkerService);
const telemetryService = accessor.get(ITelemetryService);
return formatDocumentRange(telemetryService, workerService, editor, FormatRangeType.Selection, editor.getModel().getFormattingOptions(), CancellationToken.None);
const instaService = accessor.get(IInstantiationService);
const [best] = DocumentRangeFormattingEditProviderRegistry.ordered(editor.getModel());
if (best) {
let range: Range = editor.getSelection();
if (range.isEmpty()) {
range = new Range(range.startLineNumber, 1, range.startLineNumber, editor.getModel().getLineMaxColumn(range.startLineNumber));
}
await instaService.invokeFunction(formatDocumentRangeWithProvider, best, editor, range, CancellationToken.None);
}
}
}
@@ -391,17 +299,15 @@ registerEditorAction(FormatSelectionAction);
// this is the old format action that does both (format document OR format selection)
// and we keep it here such that existing keybinding configurations etc will still work
CommandsRegistry.registerCommand('editor.action.format', accessor => {
CommandsRegistry.registerCommand('editor.action.format', async accessor => {
const editor = accessor.get(ICodeEditorService).getFocusedCodeEditor();
if (!editor || !editor.hasModel()) {
return undefined;
return;
}
const workerService = accessor.get(IEditorWorkerService);
const telemetryService = accessor.get(ITelemetryService);
const commandService = accessor.get(ICommandService);
if (editor.getSelection().isEmpty()) {
return formatDocument(telemetryService, workerService, editor, editor.getModel().getFormattingOptions(), CancellationToken.None);
await commandService.executeCommand('editor.action.formatDocument');
} else {
return formatDocumentRange(telemetryService, workerService, editor, FormatRangeType.Selection, editor.getModel().getFormattingOptions(), CancellationToken.None);
await commandService.executeCommand('editor.action.formatSelection');
}
});
+2 -2
View File
@@ -203,8 +203,8 @@ export class MarkerController implements editorCommon.IEditorContribution {
}
private readonly _editor: ICodeEditor;
private _model: MarkerModel | null;
private _widget: MarkerNavigationWidget | null;
private _model: MarkerModel | null = null;
private _widget: MarkerNavigationWidget | null = null;
private readonly _widgetVisible: IContextKey<boolean>;
private _disposeOnClose: IDisposable[] = [];
@@ -21,7 +21,7 @@ export class MoveLinesCommand implements ICommand {
private readonly _autoIndent: boolean;
private _selectionId: string;
private _moveEndPositionDown: boolean;
private _moveEndPositionDown?: boolean;
private _moveEndLineSelectionShrink: boolean;
constructor(selection: Selection, isMovingDown: boolean, autoIndent: boolean) {
@@ -196,10 +196,9 @@ suite('Editor Contrib - Line Operations', () => {
const endOfNonono = new Selection(5, 11, 5, 11);
editor.setSelections([beforeSecondWasoSelection, endOfBCCSelection, endOfNonono]);
let selections;
deleteAllLeftAction.run(null!, editor);
selections = editor.getSelections();
let selections = editor.getSelections()!;
assert.equal(model.getLineContent(2), '');
assert.equal(model.getLineContent(3), ' waso waso');
@@ -227,7 +226,7 @@ suite('Editor Contrib - Line Operations', () => {
], [5, 1, 5, 1]);
deleteAllLeftAction.run(null!, editor);
selections = editor.getSelections();
selections = editor.getSelections()!;
assert.equal(model.getLineContent(1), 'hi my name is Carlos Matos waso waso');
assert.equal(selections.length, 2);
@@ -21,6 +21,7 @@ import { Choice, Placeholder, SnippetParser, Text, TextmateSnippet } from './sni
import { ClipboardBasedVariableResolver, CompositeSnippetVariableResolver, ModelBasedVariableResolver, SelectionBasedVariableResolver, TimeBasedVariableResolver, CommentBasedVariableResolver, WorkspaceBasedVariableResolver } from './snippetVariables';
import { registerThemingParticipant } from 'vs/platform/theme/common/themeService';
import * as colors from 'vs/platform/theme/common/colorRegistry';
import { withNullAsUndefined } from 'vs/base/common/types';
registerThemingParticipant((theme, collector) => {
@@ -281,7 +282,7 @@ export class OneSnippet {
let result: Range | undefined;
const model = this._editor.getModel();
this._placeholderDecorations.forEach((decorationId) => {
const placeholderRange = model.getDecorationRange(decorationId) || undefined;
const placeholderRange = withNullAsUndefined(model.getDecorationRange(decorationId));
if (!result) {
result = placeholderRange;
} else {
@@ -18,8 +18,8 @@ export class SuggestAlternatives {
private _index: number;
private _model: CompletionModel | undefined;
private _acceptNext: ((selected: ISelectedSuggestion) => any) | undefined;
private _listener: IDisposable;
private _ignore: boolean;
private _listener: IDisposable | undefined;
private _ignore: boolean | undefined;
constructor(
private readonly _editor: ICodeEditor,
@@ -63,16 +63,16 @@ export class Colorizer {
// Send out the event to create the mode
modeService.triggerMode(language);
let tokenizationSupport = TokenizationRegistry.get(language);
const tokenizationSupport = TokenizationRegistry.get(language);
if (tokenizationSupport) {
return _colorize(lines, tabSize, tokenizationSupport);
}
let tokenizationSupportPromise = TokenizationRegistry.getPromise(language);
const tokenizationSupportPromise = TokenizationRegistry.getPromise(language);
if (tokenizationSupportPromise) {
// A tokenizer will be registered soon
return new Promise<string>((resolve, reject) => {
tokenizationSupportPromise!.then(tokenizationSupport => {
tokenizationSupportPromise.then(tokenizationSupport => {
_colorize(lines, tabSize, tokenizationSupport).then(resolve, reject);
}, reject);
});
@@ -280,7 +280,7 @@ export class StandaloneKeybindingService extends AbstractKeybindingService {
}));
}
public addDynamicKeybinding(commandId: string, _keybinding: number, handler: ICommandHandler, when: ContextKeyExpr | null): IDisposable {
public addDynamicKeybinding(commandId: string, _keybinding: number, handler: ICommandHandler, when: ContextKeyExpr | undefined): IDisposable {
const keybinding = createKeybinding(_keybinding, OS);
if (!keybinding) {
throw new Error(`Invalid keybinding`);
@@ -342,7 +342,7 @@ export class StandaloneKeybindingService extends AbstractKeybindingService {
private _toNormalizedKeybindingItems(items: IKeybindingItem[], isDefault: boolean): ResolvedKeybindingItem[] {
let result: ResolvedKeybindingItem[] = [], resultLen = 0;
for (const item of items) {
const when = (item.when ? item.when.normalize() : null);
const when = (item.when ? item.when.normalize() : undefined);
const keybinding = item.keybinding;
if (!keybinding) {
@@ -665,9 +665,5 @@ export class SimpleLayoutService implements ILayoutService {
return this._container;
}
get hasWorkbench(): boolean {
return false;
}
constructor(private _container: HTMLElement) { }
}
@@ -202,7 +202,12 @@ export class DynamicStandaloneServices extends Disposable {
let contextViewService = ensure(IContextViewService, () => this._register(new ContextViewService(layoutService)));
ensure(IContextMenuService, () => this._register(new ContextMenuService(layoutService, telemetryService, notificationService, contextViewService, keybindingService, themeService)));
ensure(IContextMenuService, () => {
const contextMenuService = new ContextMenuService(telemetryService, notificationService, contextViewService, keybindingService, themeService);
contextMenuService.configure({ blockMouse: false }); // we do not want that in the standalone editor
return this._register(contextMenuService);
});
ensure(IMenuService, () => new MenuService(commandService));
@@ -39,7 +39,7 @@ suite('StandaloneKeybindingService', () => {
let commandInvoked = false;
keybindingService.addDynamicKeybinding('testCommand', KeyCode.F9, () => {
commandInvoked = true;
}, null);
}, undefined);
keybindingService.testDispatch({
_standardKeyboardEventBrand: true,
@@ -13,7 +13,7 @@ import { IResourceInput } from 'vs/platform/editor/common/editor';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
export class TestCodeEditorService extends AbstractCodeEditorService {
public lastInput: IResourceInput;
public lastInput?: IResourceInput;
public getActiveCodeEditor(): ICodeEditor | null { return null; }
public openCodeEditor(input: IResourceInput, source: ICodeEditor | null, sideBySide?: boolean): Promise<ICodeEditor | null> {
this.lastInput = input;
@@ -30,7 +30,7 @@ suite('OpenerService', function () {
test('delegate to editorService, scheme:///fff', function () {
const openerService = new OpenerService(editorService, NullCommandService);
openerService.open(URI.parse('another:///somepath'));
assert.equal(editorService.lastInput.options!.selection, undefined);
assert.equal(editorService.lastInput!.options!.selection, undefined);
});
test('delegate to editorService, scheme:///fff#L123', function () {
@@ -38,22 +38,22 @@ suite('OpenerService', function () {
const openerService = new OpenerService(editorService, NullCommandService);
openerService.open(URI.parse('file:///somepath#L23'));
assert.equal(editorService.lastInput.options!.selection!.startLineNumber, 23);
assert.equal(editorService.lastInput.options!.selection!.startColumn, 1);
assert.equal(editorService.lastInput.options!.selection!.endLineNumber, undefined);
assert.equal(editorService.lastInput.options!.selection!.endColumn, undefined);
assert.equal(editorService.lastInput.resource.fragment, '');
assert.equal(editorService.lastInput!.options!.selection!.startLineNumber, 23);
assert.equal(editorService.lastInput!.options!.selection!.startColumn, 1);
assert.equal(editorService.lastInput!.options!.selection!.endLineNumber, undefined);
assert.equal(editorService.lastInput!.options!.selection!.endColumn, undefined);
assert.equal(editorService.lastInput!.resource.fragment, '');
openerService.open(URI.parse('another:///somepath#L23'));
assert.equal(editorService.lastInput.options!.selection!.startLineNumber, 23);
assert.equal(editorService.lastInput.options!.selection!.startColumn, 1);
assert.equal(editorService.lastInput!.options!.selection!.startLineNumber, 23);
assert.equal(editorService.lastInput!.options!.selection!.startColumn, 1);
openerService.open(URI.parse('another:///somepath#L23,45'));
assert.equal(editorService.lastInput.options!.selection!.startLineNumber, 23);
assert.equal(editorService.lastInput.options!.selection!.startColumn, 45);
assert.equal(editorService.lastInput.options!.selection!.endLineNumber, undefined);
assert.equal(editorService.lastInput.options!.selection!.endColumn, undefined);
assert.equal(editorService.lastInput.resource.fragment, '');
assert.equal(editorService.lastInput!.options!.selection!.startLineNumber, 23);
assert.equal(editorService.lastInput!.options!.selection!.startColumn, 45);
assert.equal(editorService.lastInput!.options!.selection!.endLineNumber, undefined);
assert.equal(editorService.lastInput!.options!.selection!.endColumn, undefined);
assert.equal(editorService.lastInput!.resource.fragment, '');
});
test('delegate to editorService, scheme:///fff#123,123', function () {
@@ -61,18 +61,18 @@ suite('OpenerService', function () {
const openerService = new OpenerService(editorService, NullCommandService);
openerService.open(URI.parse('file:///somepath#23'));
assert.equal(editorService.lastInput.options!.selection!.startLineNumber, 23);
assert.equal(editorService.lastInput.options!.selection!.startColumn, 1);
assert.equal(editorService.lastInput.options!.selection!.endLineNumber, undefined);
assert.equal(editorService.lastInput.options!.selection!.endColumn, undefined);
assert.equal(editorService.lastInput.resource.fragment, '');
assert.equal(editorService.lastInput!.options!.selection!.startLineNumber, 23);
assert.equal(editorService.lastInput!.options!.selection!.startColumn, 1);
assert.equal(editorService.lastInput!.options!.selection!.endLineNumber, undefined);
assert.equal(editorService.lastInput!.options!.selection!.endColumn, undefined);
assert.equal(editorService.lastInput!.resource.fragment, '');
openerService.open(URI.parse('file:///somepath#23,45'));
assert.equal(editorService.lastInput.options!.selection!.startLineNumber, 23);
assert.equal(editorService.lastInput.options!.selection!.startColumn, 45);
assert.equal(editorService.lastInput.options!.selection!.endLineNumber, undefined);
assert.equal(editorService.lastInput.options!.selection!.endColumn, undefined);
assert.equal(editorService.lastInput.resource.fragment, '');
assert.equal(editorService.lastInput!.options!.selection!.startLineNumber, 23);
assert.equal(editorService.lastInput!.options!.selection!.startColumn, 45);
assert.equal(editorService.lastInput!.options!.selection!.endLineNumber, undefined);
assert.equal(editorService.lastInput!.options!.selection!.endColumn, undefined);
assert.equal(editorService.lastInput!.resource.fragment, '');
});
test('delegate to commandsService, command:someid', function () {
+2
View File
@@ -5205,6 +5205,7 @@ declare namespace monaco.languages {
* the formatting-feature.
*/
export interface DocumentFormattingEditProvider {
readonly displayName?: string;
/**
* Provide formatting edits for a whole document.
*/
@@ -5216,6 +5217,7 @@ declare namespace monaco.languages {
* the formatting-feature.
*/
export interface DocumentRangeFormattingEditProvider {
readonly displayName?: string;
/**
* Provide formatting edits for a range in a document.
*
@@ -110,7 +110,7 @@ class Menu implements IMenu {
const [id, items] = group;
const activeActions: Array<MenuItemAction | SubmenuItemAction> = [];
for (const item of items) {
if (this._contextKeyService.contextMatchesRules(item.when || null)) {
if (this._contextKeyService.contextMatchesRules(item.when)) {
const action = isIMenuItem(item) ? new MenuItemAction(item.command, item.alt, options, this._contextKeyService, this._commandService) : new SubmenuItemAction(item);
activeActions.push(action);
}
@@ -454,7 +454,7 @@ export class Configuration {
if (workspace && resource) {
const root = workspace.getFolder(resource);
if (root) {
return this._folderConfigurations.get(root.uri) || null;
return types.withUndefinedAsNull(this._folderConfigurations.get(root.uri));
}
}
return null;
@@ -19,7 +19,7 @@ import { testFile } from 'vs/base/test/node/utils';
class SettingsTestEnvironmentService extends EnvironmentService {
constructor(args: ParsedArgs, _execPath: string, private customAppSettingsHome) {
constructor(args: ParsedArgs, _execPath: string, private customAppSettingsHome: string) {
super(args, _execPath);
}
@@ -252,7 +252,7 @@ export abstract class AbstractContextKeyService implements IContextKeyService {
return new ScopedContextKeyService(this, this._onDidChangeContextKey, domNode);
}
public contextMatchesRules(rules: ContextKeyExpr | null): boolean {
public contextMatchesRules(rules: ContextKeyExpr | undefined): boolean {
if (this._isDisposed) {
throw new Error(`AbstractContextKeyService has been disposed`);
}
@@ -58,14 +58,15 @@ export abstract class ContextKeyExpr {
public static greaterThanEquals(key: string, value: any): ContextKeyExpr {
return new ContextKeyGreaterThanEqualsExpr(key, value);
}
public static lessThanEquals(key: string, value: any): ContextKeyExpr {
return new ContextKeyLessThanEqualsExpr(key, value);
}
//
public static deserialize(serialized: string | null | undefined, strict: boolean = false): ContextKeyExpr | null {
public static deserialize(serialized: string | null | undefined, strict: boolean = false): ContextKeyExpr | undefined {
if (!serialized) {
return null;
return undefined;
}
let pieces = serialized.split('&&');
@@ -167,7 +168,7 @@ export abstract class ContextKeyExpr {
public abstract getType(): ContextKeyExprType;
public abstract equals(other: ContextKeyExpr): boolean;
public abstract evaluate(context: IContext): boolean;
public abstract normalize(): ContextKeyExpr | null;
public abstract normalize(): ContextKeyExpr | undefined;
public abstract serialize(): string;
public abstract keys(): string[];
public abstract map(mapFnc: IContextKeyExprMapper): ContextKeyExpr;
@@ -549,9 +550,9 @@ export class ContextKeyAndExpr implements ContextKeyExpr {
return expr;
}
public normalize(): ContextKeyExpr | null {
public normalize(): ContextKeyExpr | undefined {
if (this.expr.length === 0) {
return null;
return undefined;
}
if (this.expr.length === 1) {
@@ -762,7 +763,7 @@ export interface IContextKeyService {
onDidChangeContext: Event<IContextKeyChangeEvent>;
createKey<T>(key: string, defaultValue: T | undefined): IContextKey<T>;
contextMatchesRules(rules: ContextKeyExpr | null): boolean;
contextMatchesRules(rules: ContextKeyExpr | undefined): boolean;
getContextKeyValue<T>(key: string): T | undefined;
createScoped(target?: IContextKeyServiceTarget): IContextKeyService;
@@ -5,50 +5,38 @@
import 'vs/css!./contextMenuHandler';
import { combinedDisposable, IDisposable, dispose } from 'vs/base/common/lifecycle';
import { StandardMouseEvent } from 'vs/base/browser/mouseEvent';
import { combinedDisposable, IDisposable } from 'vs/base/common/lifecycle';
import { ActionRunner, IRunEvent } from 'vs/base/common/actions';
import { Menu } from 'vs/base/browser/ui/menu/menu';
import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { IContextMenuDelegate } from 'vs/base/browser/contextmenu';
import { addDisposableListener, EventType, $, removeNode } from 'vs/base/browser/dom';
import { EventType, $, removeNode } from 'vs/base/browser/dom';
import { attachMenuStyler } from 'vs/platform/theme/common/styler';
import { domEvent } from 'vs/base/browser/event';
import { ILayoutService } from 'vs/platform/layout/browser/layoutService';
export interface IContextMenuHandlerOptions {
blockMouse: boolean;
}
export class ContextMenuHandler {
private element: HTMLElement | null;
private elementDisposable: IDisposable;
private menuContainerElement: HTMLElement | null;
private focusToReturn: HTMLElement;
private block: HTMLElement | null;
private options: IContextMenuHandlerOptions = { blockMouse: true };
constructor(
private layoutService: ILayoutService,
private contextViewService: IContextViewService,
private telemetryService: ITelemetryService,
private notificationService: INotificationService,
private keybindingService: IKeybindingService,
private themeService: IThemeService
) {
this.setContainer(this.layoutService.container);
}
) { }
setContainer(container: HTMLElement | null): void {
if (this.element) {
this.elementDisposable = dispose(this.elementDisposable);
this.element = null;
}
if (container) {
this.element = container;
this.elementDisposable = addDisposableListener(this.element, EventType.MOUSE_DOWN, (e) => this.onMouseDown(e as MouseEvent));
}
configure(options: IContextMenuHandlerOptions): void {
this.options = options;
}
showContextMenu(delegate: IContextMenuDelegate): void {
@@ -67,8 +55,6 @@ export class ContextMenuHandler {
anchorAlignment: delegate.anchorAlignment,
render: (container) => {
this.menuContainerElement = container;
let className = delegate.getMenuClassName ? delegate.getMenuClassName() : '';
if (className) {
@@ -76,7 +62,7 @@ export class ContextMenuHandler {
}
// Render invisible div to block mouse interaction in the rest of the UI
if (this.layoutService.hasWorkbench) {
if (this.options.blockMouse) {
this.block = container.appendChild($('.context-view-block'));
}
@@ -120,8 +106,6 @@ export class ContextMenuHandler {
if (this.focusToReturn) {
this.focusToReturn.focus();
}
this.menuContainerElement = null;
}
});
}
@@ -150,27 +134,4 @@ export class ContextMenuHandler {
this.notificationService.error(e.error);
}
}
private onMouseDown(e: MouseEvent): void {
if (!this.menuContainerElement) {
return;
}
let event = new StandardMouseEvent(e);
let element: HTMLElement | null = event.target;
while (element) {
if (element === this.menuContainerElement) {
return;
}
element = element.parentElement;
}
this.contextViewService.hideContextView();
}
dispose(): void {
this.setContainer(null);
}
}
@@ -3,7 +3,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { ContextMenuHandler } from './contextMenuHandler';
import { ContextMenuHandler, IContextMenuHandlerOptions } from './contextMenuHandler';
import { IContextViewService, IContextMenuService } from './contextView';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { Event, Emitter } from 'vs/base/common/event';
@@ -12,7 +12,6 @@ import { IContextMenuDelegate } from 'vs/base/browser/contextmenu';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { Disposable } from 'vs/base/common/lifecycle';
import { ILayoutService } from 'vs/platform/layout/browser/layoutService';
export class ContextMenuService extends Disposable implements IContextMenuService {
_serviceBrand: any;
@@ -23,7 +22,6 @@ export class ContextMenuService extends Disposable implements IContextMenuServic
private contextMenuHandler: ContextMenuHandler;
constructor(
@ILayoutService layoutService: ILayoutService,
@ITelemetryService telemetryService: ITelemetryService,
@INotificationService notificationService: INotificationService,
@IContextViewService contextViewService: IContextViewService,
@@ -32,15 +30,11 @@ export class ContextMenuService extends Disposable implements IContextMenuServic
) {
super();
this.contextMenuHandler = this._register(new ContextMenuHandler(layoutService, contextViewService, telemetryService, notificationService, keybindingService, themeService));
this.contextMenuHandler = new ContextMenuHandler(contextViewService, telemetryService, notificationService, keybindingService, themeService);
}
dispose(): void {
this.contextMenuHandler.dispose();
}
setContainer(container: HTMLElement): void {
this.contextMenuHandler.setContainer(container);
configure(options: IContextMenuHandlerOptions): void {
this.contextMenuHandler.configure(options);
}
// ContextMenu
@@ -391,7 +391,7 @@ function collectWorkspaceStats(folder: string, filter: string[]): Promise<Worksp
const MAX_FILES = 20000;
function walk(dir: string, filter: string[], token, done: (allFiles: string[]) => void): void {
function walk(dir: string, filter: string[], token: { count: any; maxReached: any; }, done: (allFiles: string[]) => void): void {
let results: string[] = [];
readdir(dir, async (err, files) => {
// Ignore folders that can't be read
@@ -11,7 +11,7 @@ import { parseExtensionHostPort, parseUserDataDir } from 'vs/platform/environmen
suite('EnvironmentService', () => {
test('parseExtensionHostPort when built', () => {
const parse = a => parseExtensionHostPort(parseArgs(a), true);
const parse = (a: string[]) => parseExtensionHostPort(parseArgs(a), true);
assert.deepEqual(parse([]), { port: null, break: false, debugId: undefined });
assert.deepEqual(parse(['--debugPluginHost']), { port: null, break: false, debugId: undefined });
@@ -28,7 +28,7 @@ suite('EnvironmentService', () => {
});
test('parseExtensionHostPort when unbuilt', () => {
const parse = a => parseExtensionHostPort(parseArgs(a), false);
const parse = (a: string[]) => parseExtensionHostPort(parseArgs(a), false);
assert.deepEqual(parse([]), { port: 5870, break: false, debugId: undefined });
assert.deepEqual(parse(['--debugPluginHost']), { port: 5870, break: false, debugId: undefined });
@@ -45,7 +45,7 @@ suite('EnvironmentService', () => {
});
test('userDataPath', () => {
const parse = (a, b: { cwd: () => string, env: { [key: string]: string } }) => parseUserDataDir(parseArgs(a), <any>b);
const parse = (a: string[], b: { cwd: () => string, env: { [key: string]: string } }) => parseUserDataDir(parseArgs(a), <any>b);
assert.equal(parse(['--user-data-dir', './dir'], { cwd: () => '/foo', env: {} }), path.resolve('/foo/dir'),
'should use cwd when --user-data-dir is specified');
@@ -26,7 +26,7 @@ export function getGalleryExtensionId(publisher: string, name: string): string {
export function groupByExtension<T>(extensions: T[], getExtensionIdentifier: (t: T) => IExtensionIdentifier): T[][] {
const byExtension: T[][] = [];
const findGroup = extension => {
const findGroup = (extension: T) => {
for (const group of byExtension) {
if (group.some(e => areSameExtensions(getExtensionIdentifier(e), getExtensionIdentifier(extension)))) {
return group;
@@ -13,7 +13,7 @@ export interface ITranslations {
}
export function localizeManifest(manifest: IExtensionManifest, translations: ITranslations): IExtensionManifest {
const patcher = value => {
const patcher = (value: string) => {
if (typeof value !== 'string') {
return undefined;
}
@@ -54,7 +54,7 @@ export class ExtensionsLifecycle extends Disposable {
return new Promise<void>((c, e) => {
const extensionLifecycleProcess = this.start(lifecycleHook, lifecycleType, args, extension);
let timeoutHandler;
let timeoutHandler: any;
const onexit = (error?: string) => {
if (timeoutHandler) {
@@ -44,7 +44,7 @@ export class ExtensionManagementChannel implements IServerChannel {
this.onDidUninstallExtension = Event.buffer(service.onDidUninstallExtension, true);
}
listen(context, event: string): Event<any> {
listen(context: any, event: string): Event<any> {
const uriTransformer = this.getUriTransformer(context);
switch (event) {
case 'onInstallExtension': return this.onInstallExtension;
@@ -56,7 +56,7 @@ export class ExtensionManagementChannel implements IServerChannel {
throw new Error('Invalid listen');
}
call(context, command: string, args?: any): Promise<any> {
call(context: any, command: string, args?: any): Promise<any> {
const uriTransformer: IURITransformer | null = this.getUriTransformer(context);
switch (command) {
case 'zip': return this.service.zip(transformIncomingExtension(args[0], uriTransformer)).then(uri => transformOutgoingURI(uri, uriTransformer));
@@ -170,7 +170,7 @@ export class ExtensionManagementService extends Disposable implements IExtension
private collectFiles(extension: ILocalExtension): Promise<IFile[]> {
const collectFilesFromDirectory = async (dir): Promise<string[]> => {
const collectFilesFromDirectory = async (dir: string): Promise<string[]> => {
let entries = await pfs.readdir(dir);
entries = entries.map(e => path.join(dir, e));
const stats = await Promise.all(entries.map(e => pfs.stat(e)));
@@ -288,7 +288,7 @@ export class ExtensionManagementService extends Disposable implements IExtension
this.reportTelemetry(this.getTelemetryEvent(operation), getGalleryExtensionTelemetryData(extension), new Date().getTime() - startTime, undefined);
};
const onDidInstallExtensionFailure = (extension: IGalleryExtension, operation: InstallOperation, error) => {
const onDidInstallExtensionFailure = (extension: IGalleryExtension, operation: InstallOperation, error: Error) => {
const errorCode = error && (<ExtensionManagementError>error).code ? (<ExtensionManagementError>error).code : ERROR_UNKNOWN;
this.logService.error(`Failed to install extension:`, extension.identifier.id, error ? error.message : errorCode);
this._onDidInstallExtension.fire({ identifier: extension.identifier, gallery: extension, operation, error: errorCode });
+69 -21
View File
@@ -84,13 +84,18 @@ export interface IFileService {
* If the optional parameter "resolveSingleChildDescendants" is specified in options,
* the stat service is asked to automatically resolve child folders that only
* contain a single element.
*
* If the optional parameter "resolveMetadata" is specified in options,
* the stat will contain metadata information such as size, mtime and etag.
*/
resolveFile(resource: URI, options: IResolveMetadataFileOptions): Promise<IFileStatWithMetadata>;
resolveFile(resource: URI, options?: IResolveFileOptions): Promise<IFileStat>;
/**
* Same as resolveFile but supports resolving multiple resources in parallel.
* If one of the resolve targets fails to resolve returns a fake IFileStat instead of making the whole call fail.
*/
resolveFiles(toResolve: { resource: URI, options: IResolveMetadataFileOptions }[]): Promise<IResolveFileResult[]>;
resolveFiles(toResolve: { resource: URI, options?: IResolveFileOptions }[]): Promise<IResolveFileResult[]>;
/**
@@ -115,21 +120,21 @@ export interface IFileService {
/**
* Updates the content replacing its previous value.
*/
updateContent(resource: URI, value: string | ITextSnapshot, options?: IUpdateContentOptions): Promise<IFileStat>;
updateContent(resource: URI, value: string | ITextSnapshot, options?: IUpdateContentOptions): Promise<IFileStatWithMetadata>;
/**
* Moves the file to a new path identified by the resource.
*
* The optional parameter overwrite can be set to replace an existing file at the location.
*/
moveFile(source: URI, target: URI, overwrite?: boolean): Promise<IFileStat>;
moveFile(source: URI, target: URI, overwrite?: boolean): Promise<IFileStatWithMetadata>;
/**
* Copies the file to a path identified by the resource.
*
* The optional parameter overwrite can be set to replace an existing file at the location.
*/
copyFile(source: URI, target: URI, overwrite?: boolean): Promise<IFileStat>;
copyFile(source: URI, target: URI, overwrite?: boolean): Promise<IFileStatWithMetadata>;
/**
* Creates a new file with the given path. The returned promise
@@ -137,13 +142,13 @@ export interface IFileService {
*
* The optional parameter content can be used as value to fill into the new file.
*/
createFile(resource: URI, content?: string, options?: ICreateFileOptions): Promise<IFileStat>;
createFile(resource: URI, content?: string, options?: ICreateFileOptions): Promise<IFileStatWithMetadata>;
/**
* Creates a new folder with the given path. The returned promise
* will have the stat model object as a result.
*/
createFolder(resource: URI): Promise<IFileStat>;
createFolder(resource: URI): Promise<IFileStatWithMetadata>;
/**
* Deletes the provided file. The optional useTrash parameter allows to
@@ -194,9 +199,9 @@ export enum FileType {
export interface IStat {
type: FileType;
mtime: number;
ctime: number;
size: number;
mtime?: number;
ctime?: number;
size?: number;
}
export interface IWatchOptions {
@@ -329,7 +334,7 @@ export const enum FileOperation {
export class FileOperationEvent {
constructor(private _resource: URI, private _operation: FileOperation, private _target?: IFileStat) {
constructor(private _resource: URI, private _operation: FileOperation, private _target?: IFileStatWithMetadata) {
}
get resource(): URI {
@@ -481,7 +486,7 @@ export function isParent(path: string, candidate: string, ignoreCase?: boolean):
return path.indexOf(candidate) === 0;
}
export interface IBaseStat {
interface IBaseStat {
/**
* The unified resource identifier of this file or folder.
@@ -494,15 +499,29 @@ export interface IBaseStat {
*/
name: string;
/**
* The size of the file.
*
* The value may or may not be resolved as
* it is optional.
*/
size?: number;
/**
* The last modifictaion date represented
* as millis from unix epoch.
*
* The value may or may not be resolved as
* it is optional.
*/
mtime: number;
mtime?: number;
/**
* A unique identifier thet represents the
* current state of the file or directory.
*
* The value may or may not be resolved as
* it is optional.
*/
etag?: string;
@@ -512,6 +531,12 @@ export interface IBaseStat {
isReadonly?: boolean;
}
export interface IBaseStatWithMetadata extends IBaseStat {
mtime: number;
etag: string;
size: number;
}
/**
* A file resource with meta information.
*/
@@ -532,11 +557,13 @@ export interface IFileStat extends IBaseStat {
* The children of the file stat or undefined if none.
*/
children?: IFileStat[];
}
/**
* The size of the file if known.
*/
size?: number;
export interface IFileStatWithMetadata extends IFileStat, IBaseStatWithMetadata {
mtime: number;
etag: string;
size: number;
children?: IFileStatWithMetadata[];
}
export interface IResolveFileResult {
@@ -544,10 +571,14 @@ export interface IResolveFileResult {
success: boolean;
}
export interface IResolveFileResultWithMetadata extends IResolveFileResult {
stat?: IFileStatWithMetadata;
}
/**
* Content and meta information of a file.
*/
export interface IContent extends IBaseStat {
export interface IContent extends IBaseStatWithMetadata {
/**
* The content of a text file.
@@ -614,7 +645,7 @@ export function snapshotToString(snapshot: ITextSnapshot): string {
/**
* Streamable content and meta information of a file.
*/
export interface IStreamContent extends IBaseStat {
export interface IStreamContent extends IBaseStatWithMetadata {
/**
* The streamable content of a text file.
@@ -712,6 +743,16 @@ export interface IResolveFileOptions {
* Automatically continue resolving children of a directory if the number of children is 1.
*/
resolveSingleChildDescendants?: boolean;
/**
* Will resolve mtime, size and etag of files if enabled. This can have a negative impact
* on performance and thus should only be used when these values are required.
*/
resolveMetadata?: boolean;
}
export interface IResolveMetadataFileOptions extends IResolveFileOptions {
resolveMetadata: true;
}
export interface ICreateFileOptions {
@@ -1033,6 +1074,17 @@ export enum FileKind {
export const MIN_MAX_MEMORY_SIZE_MB = 2048;
export const FALLBACK_MAX_MEMORY_SIZE_MB = 4096;
export function etag(mtime: number, size: number): string;
export function etag(mtime: number | undefined, size: number | undefined): string | undefined;
export function etag(mtime: number | undefined, size: number | undefined): string | undefined {
if (typeof size !== 'number' || typeof mtime !== 'number') {
return undefined;
}
return mtime.toString(29) + size.toString(31);
}
// TODO@ben remove traces of legacy file service
export const ILegacyFileService = createDecorator<ILegacyFileService>('legacyFileService');
export interface ILegacyFileService {
@@ -1049,10 +1101,6 @@ export interface ILegacyFileService {
updateContent(resource: URI, value: string | ITextSnapshot, options?: IUpdateContentOptions): Promise<IFileStat>;
moveFile(source: URI, target: URI, overwrite?: boolean): Promise<IFileStat>;
copyFile(source: URI, target: URI, overwrite?: boolean): Promise<IFileStat>;
createFile(resource: URI, content?: string, options?: ICreateFileOptions): Promise<IFileStat>;
del(resource: URI, options?: { useTrash?: boolean, recursive?: boolean }): Promise<void>;
@@ -71,7 +71,7 @@ class Service1Consumer {
class Target2Dep {
constructor(@IService1 service1: IService1, @IService2 service2) {
constructor(@IService1 service1: IService1, @IService2 service2: Service2) {
assert.ok(service1 instanceof Service1);
assert.ok(service2 instanceof Service2);
}
@@ -99,7 +99,7 @@ class TargetOptional {
}
class DependentServiceTarget {
constructor(@IDependentService d) {
constructor(@IDependentService d: IDependentService) {
assert.ok(d);
assert.equal(d.name, 'farboo');
}
@@ -72,7 +72,7 @@ export class IssueService implements IIssueService {
}
});
ipcMain.on('vscode:workbenchCommand', (_: unknown, commandInfo) => {
ipcMain.on('vscode:workbenchCommand', (_: unknown, commandInfo: { id: any; from: any; args: any; }) => {
const { id, from, args } = commandInfo;
let parentWindow: BrowserWindow | null;
@@ -92,7 +92,7 @@ export class IssueService implements IIssueService {
}
});
ipcMain.on('vscode:openExternal', (_: unknown, arg) => {
ipcMain.on('vscode:openExternal', (_: unknown, arg: string) => {
this.windowsService.openExternal(arg);
});
@@ -50,7 +50,7 @@ export class KeybindingResolver {
}
}
private static _isTargetedForRemoval(defaultKb: ResolvedKeybindingItem, keypressFirstPart: string | null, keypressChordPart: string | null, command: string, when: ContextKeyExpr | null): boolean {
private static _isTargetedForRemoval(defaultKb: ResolvedKeybindingItem, keypressFirstPart: string | null, keypressChordPart: string | null, command: string, when: ContextKeyExpr | undefined): boolean {
if (defaultKb.command !== command) {
return false;
}
@@ -172,7 +172,7 @@ export class KeybindingResolver {
* Returns true if it is provable `a` implies `b`.
* **Precondition**: Assumes `a` and `b` are normalized!
*/
public static whenIsEntirelyIncluded(a: ContextKeyExpr | null, b: ContextKeyExpr | null): boolean {
public static whenIsEntirelyIncluded(a: ContextKeyExpr | null | undefined, b: ContextKeyExpr | null | undefined): boolean {
if (!b) {
return true;
}
@@ -304,7 +304,7 @@ export class KeybindingResolver {
return null;
}
public static contextMatchesRules(context: IContext, rules: ContextKeyExpr | null): boolean {
public static contextMatchesRules(context: IContext, rules: ContextKeyExpr | null | undefined): boolean {
if (!rules) {
return true;
}
@@ -49,7 +49,7 @@ export interface IKeybindingRule2 {
id: string;
args?: any;
weight: number;
when: ContextKeyExpr | null;
when: ContextKeyExpr | undefined;
}
export const enum KeybindingWeight {
@@ -15,10 +15,10 @@ export class ResolvedKeybindingItem {
public readonly bubble: boolean;
public readonly command: string | null;
public readonly commandArgs: any;
public readonly when: ContextKeyExpr | null;
public readonly when: ContextKeyExpr | undefined;
public readonly isDefault: boolean;
constructor(resolvedKeybinding: ResolvedKeybinding | null, command: string | null, commandArgs: any, when: ContextKeyExpr | null, isDefault: boolean) {
constructor(resolvedKeybinding: ResolvedKeybinding | null, command: string | null, commandArgs: any, when: ContextKeyExpr | undefined, isDefault: boolean) {
this.resolvedKeybinding = resolvedKeybinding;
this.keypressParts = resolvedKeybinding ? removeElementsAfterNulls(resolvedKeybinding.getDispatchParts()) : [];
this.bubble = (command ? command.charCodeAt(0) === CharCode.Caret : false);
@@ -178,7 +178,7 @@ suite('AbstractKeybindingService', () => {
statusMessageCallsDisposed = null;
});
function kbItem(keybinding: number, command: string, when: ContextKeyExpr | null = null): ResolvedKeybindingItem {
function kbItem(keybinding: number, command: string, when?: ContextKeyExpr): ResolvedKeybindingItem {
const resolvedKeybinding = (keybinding !== 0 ? new USLayoutResolvedKeybinding(createKeybinding(keybinding, OS)!, OS) : null);
return new ResolvedKeybindingItem(
resolvedKeybinding,
@@ -26,7 +26,7 @@ suite('KeybindingResolver', () => {
resolvedKeybinding,
command,
commandArgs,
when ? when.normalize() : null,
when ? when.normalize() : undefined,
isDefault
);
}
@@ -215,7 +215,8 @@ export class LaunchService implements ILaunchService {
preferNewWindow: !args['reuse-window'] && !args.wait,
forceReuseWindow: args['reuse-window'],
diffMode: args.diff,
addMode: args.add
addMode: args.add,
noRecentEntry: !!args['skip-add-to-recently-opened']
});
}
@@ -32,10 +32,4 @@ export interface ILayoutService {
* event carries the dimensions of the container as part of it.
*/
readonly onLayout: Event<IDimension>;
/**
* Indicates if the layout has a workbench surrounding the editor
*/
readonly hasWorkbench: boolean;
}
@@ -56,7 +56,7 @@ export class LifecycleService extends AbstractLifecycleService {
const windowId = this.windowService.getCurrentWindowId();
// Main side indicates that window is about to unload, check for vetos
ipc.on('vscode:onBeforeUnload', (event, reply: { okChannel: string, cancelChannel: string, reason: ShutdownReason }) => {
ipc.on('vscode:onBeforeUnload', (_event: unknown, reply: { okChannel: string, cancelChannel: string, reason: ShutdownReason }) => {
this.logService.trace(`lifecycle: onBeforeUnload (reason: ${reply.reason})`);
// trigger onBeforeShutdown events and veto collecting
@@ -75,7 +75,7 @@ export class LifecycleService extends AbstractLifecycleService {
});
// Main side indicates that we will indeed shutdown
ipc.on('vscode:onWillUnload', (event, reply: { replyChannel: string, reason: ShutdownReason }) => {
ipc.on('vscode:onWillUnload', (_event: unknown, reply: { replyChannel: string, reason: ShutdownReason }) => {
this.logService.trace(`lifecycle: onWillUnload (reason: ${reply.reason})`);
// trigger onWillShutdown events and joining
@@ -276,7 +276,7 @@ export class LifecycleService extends Disposable implements ILifecycleService {
});
// Window After Closing
window.win.on('closed', e => {
window.win.on('closed', () => {
this.logService.trace(`Lifecycle#window.on('closed') - window ID ${window.id}`);
// update window count
@@ -11,6 +11,7 @@ export interface IRemoteAgentEnvironment {
pid: number;
appRoot: URI;
appSettingsHome: URI;
appSettingsPath: URI;
logsPath: URI;
extensionsPath: URI;
extensionHostLogsPath: URI;

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