Archived
Merge from vscode 011858832762aaff245b2336fb1c38166e7a10fb (#4663)
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+1
-1
@@ -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
|
||||
|
||||
Vendored
+9
-9
@@ -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
|
||||
*/
|
||||
|
||||
Vendored
+1
-1
@@ -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;
|
||||
}
|
||||
Vendored
+3
-3
@@ -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;
|
||||
|
||||
Vendored
+3
-3
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
|
||||
@@ -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!;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -87,7 +87,7 @@ class MutableToken implements CancellationToken {
|
||||
|
||||
export class CancellationTokenSource {
|
||||
|
||||
private _token: CancellationToken;
|
||||
private _token?: CancellationToken;
|
||||
|
||||
get token(): CancellationToken {
|
||||
if (!this._token) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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,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;
|
||||
}
|
||||
|
||||
@@ -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', () => {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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!));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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));
|
||||
};
|
||||
|
||||
|
||||
@@ -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));
|
||||
});
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
@@ -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');
|
||||
}
|
||||
});
|
||||
|
||||
@@ -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 () {
|
||||
|
||||
Vendored
+2
@@ -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 });
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user