Merge from vscode 3d67364fbfcf676d93be64f949e9b33e7f1b969e (#5028)

This commit is contained in:
Anthony Dresser
2019-04-14 22:29:14 -07:00
committed by GitHub
parent 6dbf757385
commit 57242a2e13
210 changed files with 4898 additions and 3018 deletions

View File

@@ -68,7 +68,7 @@ export const DataTransfers = {
FILES: 'Files',
/**
* Typicaly transfer type for copy/paste transfers.
* Typically transfer type for copy/paste transfers.
*/
TEXT: 'text/plain'
};

View File

@@ -467,28 +467,6 @@ export function getComputedStyle(el: HTMLElement): CSSStyleDeclaration {
return document.defaultView!.getComputedStyle(el, null);
}
// Adapted from WinJS
// Converts a CSS positioning string for the specified element to pixels.
const convertToPixels: (element: HTMLElement, value: string) => number = (function () {
return function (element: HTMLElement, value: string): number {
return parseFloat(value) || 0;
};
})();
function getDimension(element: HTMLElement, cssPropertyName: string, jsPropertyName: string): number {
let computedStyle: CSSStyleDeclaration = getComputedStyle(element);
let value = '0';
if (computedStyle) {
if (computedStyle.getPropertyValue) {
value = computedStyle.getPropertyValue(cssPropertyName);
} else {
// IE8
value = (<any>computedStyle).getAttribute(jsPropertyName);
}
}
return convertToPixels(element, value);
}
export function getClientArea(element: HTMLElement): Dimension {
// Try with DOM clientWidth / clientHeight
@@ -514,48 +492,66 @@ export function getClientArea(element: HTMLElement): Dimension {
throw new Error('Unable to figure out browser width and height');
}
const sizeUtils = {
class SizeUtils {
// Adapted from WinJS
// Converts a CSS positioning string for the specified element to pixels.
private static convertToPixels(element: HTMLElement, value: string): number {
return parseFloat(value) || 0;
}
getBorderLeftWidth: function (element: HTMLElement): number {
return getDimension(element, 'border-left-width', 'borderLeftWidth');
},
getBorderRightWidth: function (element: HTMLElement): number {
return getDimension(element, 'border-right-width', 'borderRightWidth');
},
getBorderTopWidth: function (element: HTMLElement): number {
return getDimension(element, 'border-top-width', 'borderTopWidth');
},
getBorderBottomWidth: function (element: HTMLElement): number {
return getDimension(element, 'border-bottom-width', 'borderBottomWidth');
},
private static getDimension(element: HTMLElement, cssPropertyName: string, jsPropertyName: string): number {
let computedStyle: CSSStyleDeclaration = getComputedStyle(element);
let value = '0';
if (computedStyle) {
if (computedStyle.getPropertyValue) {
value = computedStyle.getPropertyValue(cssPropertyName);
} else {
// IE8
value = (<any>computedStyle).getAttribute(jsPropertyName);
}
}
return SizeUtils.convertToPixels(element, value);
}
getPaddingLeft: function (element: HTMLElement): number {
return getDimension(element, 'padding-left', 'paddingLeft');
},
getPaddingRight: function (element: HTMLElement): number {
return getDimension(element, 'padding-right', 'paddingRight');
},
getPaddingTop: function (element: HTMLElement): number {
return getDimension(element, 'padding-top', 'paddingTop');
},
getPaddingBottom: function (element: HTMLElement): number {
return getDimension(element, 'padding-bottom', 'paddingBottom');
},
static getBorderLeftWidth(element: HTMLElement): number {
return SizeUtils.getDimension(element, 'border-left-width', 'borderLeftWidth');
}
static getBorderRightWidth(element: HTMLElement): number {
return SizeUtils.getDimension(element, 'border-right-width', 'borderRightWidth');
}
static getBorderTopWidth(element: HTMLElement): number {
return SizeUtils.getDimension(element, 'border-top-width', 'borderTopWidth');
}
static getBorderBottomWidth(element: HTMLElement): number {
return SizeUtils.getDimension(element, 'border-bottom-width', 'borderBottomWidth');
}
getMarginLeft: function (element: HTMLElement): number {
return getDimension(element, 'margin-left', 'marginLeft');
},
getMarginTop: function (element: HTMLElement): number {
return getDimension(element, 'margin-top', 'marginTop');
},
getMarginRight: function (element: HTMLElement): number {
return getDimension(element, 'margin-right', 'marginRight');
},
getMarginBottom: function (element: HTMLElement): number {
return getDimension(element, 'margin-bottom', 'marginBottom');
},
__commaSentinel: false
};
static getPaddingLeft(element: HTMLElement): number {
return SizeUtils.getDimension(element, 'padding-left', 'paddingLeft');
}
static getPaddingRight(element: HTMLElement): number {
return SizeUtils.getDimension(element, 'padding-right', 'paddingRight');
}
static getPaddingTop(element: HTMLElement): number {
return SizeUtils.getDimension(element, 'padding-top', 'paddingTop');
}
static getPaddingBottom(element: HTMLElement): number {
return SizeUtils.getDimension(element, 'padding-bottom', 'paddingBottom');
}
static getMarginLeft(element: HTMLElement): number {
return SizeUtils.getDimension(element, 'margin-left', 'marginLeft');
}
static getMarginTop(element: HTMLElement): number {
return SizeUtils.getDimension(element, 'margin-top', 'marginTop');
}
static getMarginRight(element: HTMLElement): number {
return SizeUtils.getDimension(element, 'margin-right', 'marginRight');
}
static getMarginBottom(element: HTMLElement): number {
return SizeUtils.getDimension(element, 'margin-bottom', 'marginBottom');
}
}
// ----------------------------------------------------------------------------------------
// Position & Dimension
@@ -594,8 +590,8 @@ export function getTopLeftOffset(element: HTMLElement): { left: number; top: num
}
if (element === offsetParent) {
left += sizeUtils.getBorderLeftWidth(element);
top += sizeUtils.getBorderTopWidth(element);
left += SizeUtils.getBorderLeftWidth(element);
top += SizeUtils.getBorderTopWidth(element);
top += element.offsetTop;
left += element.offsetLeft;
offsetParent = element.offsetParent;
@@ -686,33 +682,33 @@ export const StandardWindow: IStandardWindow = new class implements IStandardWin
// Adapted from WinJS
// Gets the width of the element, including margins.
export function getTotalWidth(element: HTMLElement): number {
let margin = sizeUtils.getMarginLeft(element) + sizeUtils.getMarginRight(element);
let margin = SizeUtils.getMarginLeft(element) + SizeUtils.getMarginRight(element);
return element.offsetWidth + margin;
}
export function getContentWidth(element: HTMLElement): number {
let border = sizeUtils.getBorderLeftWidth(element) + sizeUtils.getBorderRightWidth(element);
let padding = sizeUtils.getPaddingLeft(element) + sizeUtils.getPaddingRight(element);
let border = SizeUtils.getBorderLeftWidth(element) + SizeUtils.getBorderRightWidth(element);
let padding = SizeUtils.getPaddingLeft(element) + SizeUtils.getPaddingRight(element);
return element.offsetWidth - border - padding;
}
export function getTotalScrollWidth(element: HTMLElement): number {
let margin = sizeUtils.getMarginLeft(element) + sizeUtils.getMarginRight(element);
let margin = SizeUtils.getMarginLeft(element) + SizeUtils.getMarginRight(element);
return element.scrollWidth + margin;
}
// Adapted from WinJS
// Gets the height of the content of the specified element. The content height does not include borders or padding.
export function getContentHeight(element: HTMLElement): number {
let border = sizeUtils.getBorderTopWidth(element) + sizeUtils.getBorderBottomWidth(element);
let padding = sizeUtils.getPaddingTop(element) + sizeUtils.getPaddingBottom(element);
let border = SizeUtils.getBorderTopWidth(element) + SizeUtils.getBorderBottomWidth(element);
let padding = SizeUtils.getPaddingTop(element) + SizeUtils.getPaddingBottom(element);
return element.offsetHeight - border - padding;
}
// Adapted from WinJS
// Gets the height of the element, including its margins.
export function getTotalHeight(element: HTMLElement): number {
let margin = sizeUtils.getMarginTop(element) + sizeUtils.getMarginBottom(element);
let margin = SizeUtils.getMarginTop(element) + SizeUtils.getMarginBottom(element);
return element.offsetHeight + margin;
}
@@ -836,53 +832,53 @@ export function isHTMLElement(o: any): o is HTMLElement {
export const EventType = {
// Mouse
CLICK: 'click' as 'click',
DBLCLICK: 'dblclick' as 'dblclick',
MOUSE_UP: 'mouseup' as 'mouseup',
MOUSE_DOWN: 'mousedown' as 'mousedown',
MOUSE_OVER: 'mouseover' as 'mouseover',
MOUSE_MOVE: 'mousemove' as 'mousemove',
MOUSE_OUT: 'mouseout' as 'mouseout',
MOUSE_ENTER: 'mouseenter' as 'mouseenter',
MOUSE_LEAVE: 'mouseleave' as 'mouseleave',
CONTEXT_MENU: 'contextmenu' as 'contextmenu',
WHEEL: 'wheel' as 'wheel',
CLICK: 'click',
DBLCLICK: 'dblclick',
MOUSE_UP: 'mouseup',
MOUSE_DOWN: 'mousedown',
MOUSE_OVER: 'mouseover',
MOUSE_MOVE: 'mousemove',
MOUSE_OUT: 'mouseout',
MOUSE_ENTER: 'mouseenter',
MOUSE_LEAVE: 'mouseleave',
CONTEXT_MENU: 'contextmenu',
WHEEL: 'wheel',
// Keyboard
KEY_DOWN: 'keydown' as 'keydown',
KEY_PRESS: 'keypress' as 'keypress',
KEY_UP: 'keyup' as 'keyup',
KEY_DOWN: 'keydown',
KEY_PRESS: 'keypress',
KEY_UP: 'keyup',
// HTML Document
LOAD: 'load' as 'load',
UNLOAD: 'unload' as 'unload',
ABORT: 'abort' as 'abort',
ERROR: 'error' as 'error',
RESIZE: 'resize' as 'resize',
SCROLL: 'scroll' as 'scroll',
LOAD: 'load',
UNLOAD: 'unload',
ABORT: 'abort',
ERROR: 'error',
RESIZE: 'resize',
SCROLL: 'scroll',
// Form
SELECT: 'select' as 'select',
CHANGE: 'change' as 'change',
SUBMIT: 'submit' as 'submit',
RESET: 'reset' as 'reset',
FOCUS: 'focus' as 'focus',
FOCUS_IN: 'focusin' as 'focusin',
FOCUS_OUT: 'focusout' as 'focusout',
BLUR: 'blur' as 'blur',
INPUT: 'input' as 'input',
SELECT: 'select',
CHANGE: 'change',
SUBMIT: 'submit',
RESET: 'reset',
FOCUS: 'focus',
FOCUS_IN: 'focusin',
FOCUS_OUT: 'focusout',
BLUR: 'blur',
INPUT: 'input',
// Local Storage
STORAGE: 'storage' as 'storage',
STORAGE: 'storage',
// Drag
DRAG_START: 'dragstart' as 'dragstart',
DRAG: 'drag' as 'drag',
DRAG_ENTER: 'dragenter' as 'dragenter',
DRAG_LEAVE: 'dragleave' as 'dragleave',
DRAG_OVER: 'dragover' as 'dragover',
DROP: 'drop' as 'drop',
DRAG_END: 'dragend' as 'dragend',
DRAG_START: 'dragstart',
DRAG: 'drag',
DRAG_ENTER: 'dragenter',
DRAG_LEAVE: 'dragleave',
DRAG_OVER: 'dragover',
DROP: 'drop',
DRAG_END: 'dragend',
// Animation
ANIMATION_START: browser.isWebKit ? 'webkitAnimationStart' : 'animationstart',
ANIMATION_END: browser.isWebKit ? 'webkitAnimationEnd' : 'animationend',
ANIMATION_ITERATION: browser.isWebKit ? 'webkitAnimationIteration' : 'animationiteration'
};
} as const;
export interface EventLike {
preventDefault(): void;

View File

@@ -214,10 +214,10 @@ export class Gesture extends Disposable {
}
}
private newGestureEvent(type: string, intialTarget?: EventTarget): GestureEvent {
private newGestureEvent(type: string, initialTarget?: EventTarget): GestureEvent {
let event = <GestureEvent>(<any>document.createEvent('CustomEvent'));
event.initEvent(type, false, true);
event.initialTarget = intialTarget;
event.initialTarget = initialTarget;
return event;
}

View File

@@ -126,7 +126,7 @@ export class BreadcrumbsWidget {
this._pendingLayout.dispose();
}
if (dim) {
// only meaure
// only measure
this._pendingLayout = this._updateDimensions(dim);
} else {
this._pendingLayout = this._updateScrollbar();

View File

@@ -15,6 +15,10 @@
align-items: center;
}
.monaco-workbench .dialog-modal-block.dimmed {
background: rgba(0, 0, 0, 0.3);
}
/** Dialog: Container */
.monaco-workbench .dialog-box {
display: flex;
@@ -56,16 +60,22 @@
display: flex;
flex-grow: 1;
padding: 10px 15px 20px;
align-items: center;
}
.monaco-workbench .dialog-box .dialog-message-row .dialog-icon {
flex: 0 0 30px;
height: 30px;
padding-right: 4px;
padding-left: 4px;
background-position: center;
background-repeat: no-repeat;
}
.vs .monaco-workbench .dialog-box .dialog-message-row .dialog-icon.icon-pending {
background-image: url('pending.svg');
}
.vs .monaco-workbench .dialog-box .dialog-message-row .dialog-icon.icon-info {
background-image: url('info.svg');
}
@@ -78,6 +88,10 @@
background-image: url('error.svg');
}
.vs-dark .monaco-workbench .dialog-box .dialog-message-row .dialog-icon.icon-pending {
background-image: url('pending-dark.svg');
}
.vs-dark .monaco-workbench .dialog-box .dialog-message-row .dialog-icon.icon-info,
.hc-black .monaco-workbench .dialog-box .dialog-message-row .dialog-icon.icon-info {
background-image: url('info-inverse.svg');
@@ -93,6 +107,14 @@
background-image: url('error-inverse.svg');
}
.hc-black .monaco-workbench .dialog-box .dialog-message-row .dialog-icon.icon-pending {
background-image: url('pending-hc.svg');
}
.monaco-workbench .dialog-box .dialog-message-row .dialog-icon.icon-pending {
background-size: 30px;
}
/** Dialog: Message Container */
.monaco-workbench .dialog-box .dialog-message-row .dialog-message-container {
display: flex;

View File

@@ -19,7 +19,7 @@ import { mnemonicButtonLabel } from 'vs/base/common/labels';
export interface IDialogOptions {
cancelId?: number;
detail?: string;
type?: 'none' | 'info' | 'error' | 'question' | 'warning';
type?: 'none' | 'info' | 'error' | 'question' | 'warning' | 'pending';
}
export interface IDialogStyles extends IButtonStyles {
@@ -33,6 +33,7 @@ export class Dialog extends Disposable {
private element: HTMLElement | undefined;
private modal: HTMLElement | undefined;
private buttonsContainer: HTMLElement | undefined;
private messageDetailElement: HTMLElement | undefined;
private iconElement: HTMLElement | undefined;
private toolbarContainer: HTMLElement | undefined;
private buttonGroup: ButtonGroup | undefined;
@@ -40,7 +41,7 @@ export class Dialog extends Disposable {
constructor(private container: HTMLElement, private message: string, private buttons: string[], private options: IDialogOptions) {
super();
this.modal = this.container.appendChild($('.dialog-modal-block'));
this.modal = this.container.appendChild($(`.dialog-modal-block${options.type === 'pending' ? '.dimmed' : ''}`));
this.element = this.modal.appendChild($('.dialog-box'));
hide(this.element);
@@ -56,13 +57,19 @@ export class Dialog extends Disposable {
messageElement.innerText = this.message;
}
const messageDetailElement = messageContainer.appendChild($('.dialog-message-detail'));
messageDetailElement.innerText = this.options.detail ? this.options.detail : message;
this.messageDetailElement = messageContainer.appendChild($('.dialog-message-detail'));
this.messageDetailElement.innerText = this.options.detail ? this.options.detail : message;
const toolbarRowElement = this.element.appendChild($('.dialog-toolbar-row'));
this.toolbarContainer = toolbarRowElement.appendChild($('.dialog-toolbar'));
}
updateMessage(message: string): void {
if (this.messageDetailElement) {
this.messageDetailElement.innerText = message;
}
}
async show(): Promise<number> {
return new Promise<number>((resolve) => {
if (!this.element || !this.buttonsContainer || !this.iconElement || !this.toolbarContainer) {
@@ -129,6 +136,9 @@ export class Dialog extends Disposable {
case 'warning':
addClass(this.iconElement, 'icon-warning');
break;
case 'pending':
addClass(this.iconElement, 'icon-pending');
break;
case 'none':
case 'info':
case 'question':

View File

@@ -0,0 +1,31 @@
<?xml version='1.0' standalone='no' ?>
<svg xmlns='http://www.w3.org/2000/svg' version='1.1' width='10px' height='10px'>
<style>
circle {
animation: ball 1.04s linear infinite;
}
circle:nth-child(2) { animation-delay: 0.13s; }
circle:nth-child(3) { animation-delay: 0.26s; }
circle:nth-child(4) { animation-delay: 0.39s; }
circle:nth-child(5) { animation-delay: 0.52s; }
circle:nth-child(6) { animation-delay: 0.65s; }
circle:nth-child(7) { animation-delay: 0.78s; }
circle:nth-child(8) { animation-delay: 0.91s; }
@keyframes ball {
from { opacity: 1; }
to { opacity: 0.3; }
}
</style>
<g style="fill:grey;">
<circle cx='5' cy='1' r='1' style='opacity:0.3;' />
<circle cx='7.8284' cy='2.1716' r='1' style='opacity:0.3;' />
<circle cx='9' cy='5' r='1' style='opacity:0.3;' />
<circle cx='7.8284' cy='7.8284' r='1' style='opacity:0.3;' />
<circle cx='5' cy='9' r='1' style='opacity:0.3;' />
<circle cx='2.1716' cy='7.8284' r='1' style='opacity:0.3;' />
<circle cx='1' cy='5' r='1' style='opacity:0.3;' />
<circle cx='2.1716' cy='2.1716' r='1' style='opacity:0.3;' />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1,31 @@
<?xml version='1.0' standalone='no' ?>
<svg xmlns='http://www.w3.org/2000/svg' version='1.1' width='10px' height='10px'>
<style>
circle {
animation: ball 1.04s linear infinite;
}
circle:nth-child(2) { animation-delay: 0.13s; }
circle:nth-child(3) { animation-delay: 0.26s; }
circle:nth-child(4) { animation-delay: 0.39s; }
circle:nth-child(5) { animation-delay: 0.52s; }
circle:nth-child(6) { animation-delay: 0.65s; }
circle:nth-child(7) { animation-delay: 0.78s; }
circle:nth-child(8) { animation-delay: 0.91s; }
@keyframes ball {
from { opacity: 1; }
to { opacity: 0.3; }
}
</style>
<g style="fill:white;">
<circle cx='5' cy='1' r='1' style='opacity:0.3;' />
<circle cx='7.8284' cy='2.1716' r='1' style='opacity:0.3;' />
<circle cx='9' cy='5' r='1' style='opacity:0.3;' />
<circle cx='7.8284' cy='7.8284' r='1' style='opacity:0.3;' />
<circle cx='5' cy='9' r='1' style='opacity:0.3;' />
<circle cx='2.1716' cy='7.8284' r='1' style='opacity:0.3;' />
<circle cx='1' cy='5' r='1' style='opacity:0.3;' />
<circle cx='2.1716' cy='2.1716' r='1' style='opacity:0.3;' />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1,31 @@
<?xml version='1.0' standalone='no' ?>
<svg xmlns='http://www.w3.org/2000/svg' version='1.1' width='10px' height='10px'>
<style>
circle {
animation: ball 1.04s linear infinite;
}
circle:nth-child(2) { animation-delay: 0.13s; }
circle:nth-child(3) { animation-delay: 0.26s; }
circle:nth-child(4) { animation-delay: 0.39s; }
circle:nth-child(5) { animation-delay: 0.52s; }
circle:nth-child(6) { animation-delay: 0.65s; }
circle:nth-child(7) { animation-delay: 0.78s; }
circle:nth-child(8) { animation-delay: 0.91s; }
@keyframes ball {
from { opacity: 1; }
to { opacity: 0.3; }
}
</style>
<g>
<circle cx='5' cy='1' r='1' style='opacity:0.3;' />
<circle cx='7.8284' cy='2.1716' r='1' style='opacity:0.3;' />
<circle cx='9' cy='5' r='1' style='opacity:0.3;' />
<circle cx='7.8284' cy='7.8284' r='1' style='opacity:0.3;' />
<circle cx='5' cy='9' r='1' style='opacity:0.3;' />
<circle cx='2.1716' cy='7.8284' r='1' style='opacity:0.3;' />
<circle cx='1' cy='5' r='1' style='opacity:0.3;' />
<circle cx='2.1716' cy='2.1716' r='1' style='opacity:0.3;' />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -502,7 +502,7 @@ function isMouseRightClick(event: UIEvent): boolean {
return event instanceof MouseEvent && event.button === 2;
}
const DefaultMultipleSelectionContoller = {
const DefaultMultipleSelectionController = {
isSelectionSingleChangeEvent,
isSelectionRangeChangeEvent
};
@@ -529,7 +529,7 @@ export class MouseController<T> implements IDisposable {
this.multipleSelectionSupport = !(list.options.multipleSelectionSupport === false);
if (this.multipleSelectionSupport) {
this.multipleSelectionController = list.options.multipleSelectionController || DefaultMultipleSelectionContoller;
this.multipleSelectionController = list.options.multipleSelectionController || DefaultMultipleSelectionController;
}
this.openController = list.options.openController || DefaultOpenController;
@@ -909,7 +909,7 @@ function getContiguousRangeContaining(range: number[], value: number): number[]
/**
* Given two sorted collections of numbers, returns the intersection
* betweem them (OR).
* between them (OR).
*/
function disjunction(one: number[], other: number[]): number[] {
const result: number[] = [];

View File

@@ -1,7 +1,7 @@
@font-face {
font-family: "octicons";
src: url("./octicons.ttf?4cd2299755e93a2430ba5703f4476584") format("truetype"),
url("./octicons.svg?4cd2299755e93a2430ba5703f4476584#octicons") format("svg");
src: url("./octicons.ttf?91284a5a76ea88faeb754359b7f7cd03") format("truetype"),
url("./octicons.svg?91284a5a76ea88faeb754359b7f7cd03#octicons") format("svg");
}
.octicon, .mega-octicon {
@@ -240,4 +240,5 @@ url("./octicons.svg?4cd2299755e93a2430ba5703f4476584#octicons") format("svg");
.octicon-fold-up:before { content: "\f105" }
.octicon-github-action:before { content: "\f106" }
.octicon-play:before { content: "\f107" }
.octicon-request-changes:before { content: "\f108" }
.octicon-remote:before { content: "\f108" }
.octicon-request-changes:before { content: "\f109" }

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 131 KiB

After

Width:  |  Height:  |  Size: 127 KiB

View File

@@ -523,7 +523,7 @@ export class DomScrollableElement extends ScrollableElement {
}
public scanDomNode(): void {
// widh, scrollLeft, scrollWidth, height, scrollTop, scrollHeight
// width, scrollLeft, scrollWidth, height, scrollTop, scrollHeight
this.setScrollDimensions({
width: this._element.clientWidth,
scrollWidth: this._element.scrollWidth,

View File

@@ -33,7 +33,7 @@ export const enum TreeVisibility {
export interface ITreeFilterDataResult<TFilterData> {
/**
* Whether the node should be visibile.
* Whether the node should be visible.
*/
visibility: boolean | TreeVisibility;

View File

@@ -5,6 +5,7 @@
import { ParseError, Node, JSONPath, Segment, parseTree, findNodeAtLocation } from './json';
import { Edit, format, isEOL, FormattingOptions } from './jsonFormatter';
import { mergeSort } from 'vs/base/common/arrays';
export function removeProperty(text: string, path: JSONPath, formattingOptions: FormattingOptions): Edit[] {
@@ -158,6 +159,27 @@ export function applyEdit(text: string, edit: Edit): string {
return text.substring(0, edit.offset) + edit.content + text.substring(edit.offset + edit.length);
}
export function applyEdits(text: string, edits: Edit[]): string {
let sortedEdits = mergeSort(edits, (a, b) => {
const diff = a.offset - b.offset;
if (diff === 0) {
return a.length - b.length;
}
return diff;
});
let lastModifiedOffset = text.length;
for (let i = sortedEdits.length - 1; i >= 0; i--) {
let e = sortedEdits[i];
if (e.offset + e.length <= lastModifiedOffset) {
text = applyEdit(text, e);
} else {
throw new Error('Overlapping edit');
}
lastModifiedOffset = e.offset;
}
return text;
}
export function isWS(text: string, offset: number) {
return '\r\n \t'.indexOf(text.charAt(offset)) !== -1;
}

View File

@@ -226,7 +226,7 @@ export class URI implements UriComponents {
// ---- modify to new -------------------------
public with(change: { scheme?: string; authority?: string | null; path?: string | null; query?: string | null; fragment?: string | null }): URI {
with(change: { scheme?: string; authority?: string | null; path?: string | null; query?: string | null; fragment?: string | null }): URI {
if (!change) {
return this;
@@ -279,7 +279,7 @@ export class URI implements UriComponents {
*
* @param value A string which represents an URI (see `URI#toString`).
*/
public static parse(value: string, _strict: boolean = false): URI {
static parse(value: string, _strict: boolean = false): URI {
const match = _regexp.exec(value);
if (!match) {
return new _URI(_empty, _empty, _empty, _empty, _empty);
@@ -315,7 +315,7 @@ export class URI implements UriComponents {
*
* @param path A file system path (see `URI#fsPath`)
*/
public static file(path: string): URI {
static file(path: string): URI {
let authority = _empty;
@@ -342,7 +342,7 @@ export class URI implements UriComponents {
return new _URI('file', authority, path, _empty, _empty);
}
public static from(components: { scheme: string; authority?: string; path?: string; query?: string; fragment?: string }): URI {
static from(components: { scheme: string; authority?: string; path?: string; query?: string; fragment?: string }): URI {
return new _URI(
components.scheme,
components.authority,
@@ -365,17 +365,22 @@ export class URI implements UriComponents {
*
* @param skipEncoding Do not encode the result, default is `false`
*/
public toString(skipEncoding: boolean = false): string {
toString(skipEncoding: boolean = false): string {
return _asFormatted(this, skipEncoding);
}
public toJSON(): object {
toJSON(): UriComponents {
return this;
}
static revive(data: UriComponents | any): URI {
static revive(data: UriComponents | URI): URI;
static revive(data: UriComponents | URI | undefined): URI | undefined;
static revive(data: UriComponents | URI | null): URI | null;
static revive(data: UriComponents | URI | undefined | null): URI | undefined | null;
static revive(data: UriComponents | URI | undefined | null): URI | undefined | null {
if (!data) {
return data;
// {{SQL CARBON EDIT}} @todo chlafren change back to data when we enable strict null checks
return undefined;
} else if (data instanceof URI) {
return data;
} else {
@@ -415,7 +420,7 @@ class _URI extends URI {
return this._fsPath;
}
public toString(skipEncoding: boolean = false): string {
toString(skipEncoding: boolean = false): string {
if (!skipEncoding) {
if (!this._formatted) {
this._formatted = _asFormatted(this, false);
@@ -427,7 +432,7 @@ class _URI extends URI {
}
}
toJSON(): object {
toJSON(): UriComponents {
const res = <UriState>{
$mid: 1
};

View File

@@ -14,6 +14,10 @@ export const UTF8_with_bom = 'utf8bom';
export const UTF16be = 'utf16be';
export const UTF16le = 'utf16le';
export const UTF16be_BOM = [0xFE, 0xFF];
export const UTF16le_BOM = [0xFF, 0xFE];
export const UTF8_BOM = [0xEF, 0xBB, 0xBF];
export interface IDecodeStreamOptions {
guessEncoding?: boolean;
minBytesRequiredForDetection?: number;
@@ -150,12 +154,12 @@ export function detectEncodingByBOMFromBuffer(buffer: Buffer | null, bytesRead:
const b1 = buffer.readUInt8(1);
// UTF-16 BE
if (b0 === 0xFE && b1 === 0xFF) {
if (b0 === UTF16be_BOM[0] && b1 === UTF16be_BOM[1]) {
return UTF16be;
}
// UTF-16 LE
if (b0 === 0xFF && b1 === 0xFE) {
if (b0 === UTF16le_BOM[0] && b1 === UTF16le_BOM[1]) {
return UTF16le;
}
@@ -166,7 +170,7 @@ export function detectEncodingByBOMFromBuffer(buffer: Buffer | null, bytesRead:
const b2 = buffer.readUInt8(2);
// UTF-8
if (b0 === 0xEF && b1 === 0xBB && b2 === 0xBF) {
if (b0 === UTF8_BOM[0] && b1 === UTF8_BOM[1] && b2 === UTF8_BOM[2]) {
return UTF8;
}
@@ -178,7 +182,7 @@ export function detectEncodingByBOMFromBuffer(buffer: Buffer | null, bytesRead:
* If no BOM is detected, null will be passed to callback.
*/
export function detectEncodingByBOM(file: string): Promise<string | null> {
return stream.readExactlyByFile(file, 3).then(({ buffer, bytesRead }) => detectEncodingByBOMFromBuffer(buffer, bytesRead));
return stream.readExactlyByFile(file, 3).then(({ buffer, bytesRead }) => detectEncodingByBOMFromBuffer(buffer, bytesRead), error => null);
}
const MINIMUM_THRESHOLD = 0.2;

39
src/vs/base/node/ps.sh Executable file
View File

@@ -0,0 +1,39 @@
#!/bin/sh
PAGESIZE=`getconf PAGESIZE`;
TOTAL_MEMORY=`cat /proc/meminfo | head -n 1 | awk '{print $2}'`;
# Mimic the output of ps -ax -o pid=,ppid=,pcpu=,pmem=,command=
# Read all numeric subdirectories in /proc
for pid in `cd /proc && ls -d [0-9]*`
do {
if [ -e /proc/$pid/stat ]
then
echo $pid;
# ppid is the word at index 4 in the stat file for the process
awk '{print $4}' /proc/$pid/stat;
# pcpu - calculation will be done later, this is a placeholder value
echo "0.0"
# pmem - ratio of the process's working set size to total memory.
# use the page size to convert to bytes, total memory is in KB
# multiplied by 100 to get percentage, extra 10 to be able to move
# the decimal over by one place
RESIDENT_SET_SIZE=`awk '{print $24}' /proc/$pid/stat`;
PERCENT_MEMORY=$(((1000 * $PAGESIZE * $RESIDENT_SET_SIZE) / ($TOTAL_MEMORY * 1024)));
if [ $PERCENT_MEMORY -lt 10 ]
then
# replace the last character with 0. the last character
echo $PERCENT_MEMORY | sed 's/.$/0.&/'; #pmem
else
# insert . before the last character
echo $PERCENT_MEMORY | sed 's/.$/.&/';
fi
# cmdline
xargs -0 < /proc/$pid/cmdline;
fi
} | tr "\n" "\t"; # Replace newlines with tab so that all info for a process is shown on one line
echo; # But add new lines between processes
done

View File

@@ -14,6 +14,7 @@ export function listProcesses(rootPid: number): Promise<ProcessItem> {
let rootItem: ProcessItem | undefined;
const map = new Map<number, ProcessItem>();
function addToTree(pid: number, ppid: number, cmd: string, load: number, mem: number) {
const parent = map.get(ppid);
@@ -162,64 +163,87 @@ export function listProcesses(rootPid: number): Promise<ProcessItem> {
}, windowsProcessTree.ProcessDataFlag.CommandLine | windowsProcessTree.ProcessDataFlag.Memory);
});
} else { // OS X & Linux
const CMD = '/bin/ps -ax -o pid=,ppid=,pcpu=,pmem=,command=';
const PID_CMD = /^\s*([0-9]+)\s+([0-9]+)\s+([0-9]+\.[0-9]+)\s+([0-9]+\.[0-9]+)\s+(.+)$/;
// Set numeric locale to ensure '.' is used as the decimal separator
exec(CMD, { maxBuffer: 1000 * 1024, env: { LC_NUMERIC: 'en_US.UTF-8' } }, (err, stdout, stderr) => {
if (err || stderr) {
reject(err || new Error(stderr.toString()));
} else {
const lines = stdout.toString().split('\n');
for (const line of lines) {
const matches = PID_CMD.exec(line.trim());
if (matches && matches.length === 6) {
addToTree(parseInt(matches[1]), parseInt(matches[2]), matches[5], parseFloat(matches[3]), parseFloat(matches[4]));
function calculateLinuxCpuUsage() {
// Flatten rootItem to get a list of all VSCode processes
let processes = [rootItem];
const pids: number[] = [];
while (processes.length) {
const process = processes.shift();
if (process) {
pids.push(process.pid);
if (process.children) {
processes = processes.concat(process.children);
}
}
}
if (process.platform === 'linux') {
// Flatten rootItem to get a list of all VSCode processes
let processes = [rootItem];
const pids: number[] = [];
while (processes.length) {
const process = processes.shift();
if (process) {
pids.push(process.pid);
if (process.children) {
processes = processes.concat(process.children);
}
}
// The cpu usage value reported on Linux is the average over the process lifetime,
// recalculate the usage over a one second interval
// JSON.stringify is needed to escape spaces, https://github.com/nodejs/node/issues/6803
let cmd = JSON.stringify(getPathFromAmdModule(require, 'vs/base/node/cpuUsage.sh'));
cmd += ' ' + pids.join(' ');
exec(cmd, {}, (err, stdout, stderr) => {
if (err || stderr) {
reject(err || new Error(stderr.toString()));
} else {
const cpuUsage = stdout.toString().split('\n');
for (let i = 0; i < pids.length; i++) {
const processInfo = map.get(pids[i])!;
processInfo.load = parseFloat(cpuUsage[i]);
}
// The cpu usage value reported on Linux is the average over the process lifetime,
// recalculate the usage over a one second interval
// JSON.stringify is needed to escape spaces, https://github.com/nodejs/node/issues/6803
let cmd = JSON.stringify(getPathFromAmdModule(require, 'vs/base/node/cpuUsage.sh'));
cmd += ' ' + pids.join(' ');
resolve(rootItem);
}
});
}
exec('which ps', {}, (err, stdout, stderr) => {
if (err || stderr) {
if (process.platform !== 'linux') {
reject(err || new Error(stderr.toString()));
} else {
const cmd = JSON.stringify(getPathFromAmdModule(require, 'vs/base/node/ps.sh'));
exec(cmd, {}, (err, stdout, stderr) => {
if (err || stderr) {
reject(err || new Error(stderr.toString()));
} else {
const cpuUsage = stdout.toString().split('\n');
for (let i = 0; i < pids.length; i++) {
const processInfo = map.get(pids[i])!;
processInfo.load = parseFloat(cpuUsage[i]);
}
resolve(rootItem);
parsePsOutput(stdout, addToTree);
calculateLinuxCpuUsage();
}
});
} else {
resolve(rootItem);
}
} else {
const ps = stdout.toString().trim();
const args = '-ax -o pid=,ppid=,pcpu=,pmem=,command=';
// Set numeric locale to ensure '.' is used as the decimal separator
exec(`${ps} ${args}`, { maxBuffer: 1000 * 1024, env: { LC_NUMERIC: 'en_US.UTF-8' } }, (err, stdout, stderr) => {
if (err || stderr) {
reject(err || new Error(stderr.toString()));
} else {
parsePsOutput(stdout, addToTree);
if (process.platform === 'linux') {
calculateLinuxCpuUsage();
} else {
resolve(rootItem);
}
}
});
}
});
}
});
}
function parsePsOutput(stdout: string, addToTree: (pid: number, ppid: number, cmd: string, load: number, mem: number) => void): void {
const PID_CMD = /^\s*([0-9]+)\s+([0-9]+)\s+([0-9]+\.[0-9]+)\s+([0-9]+\.[0-9]+)\s+(.+)$/;
const lines = stdout.toString().split('\n');
for (const line of lines) {
const matches = PID_CMD.exec(line.trim());
if (matches && matches.length === 6) {
addToTree(parseInt(matches[1]), parseInt(matches[2]), matches[5], parseFloat(matches[3]), parseFloat(matches[4]));
}
}
}

View File

@@ -3,7 +3,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import { URI } from 'vs/base/common/uri';
import { URI, UriComponents } from 'vs/base/common/uri';
import { isWindows } from 'vs/base/common/platform';
@@ -441,7 +441,7 @@ suite('URI', () => {
// let c = 100000;
// while (c-- > 0) {
for (let value of values) {
let data = value.toJSON();
let data = value.toJSON() as UriComponents;
let clone = URI.revive(data);
assert.equal(clone.scheme, value.scheme);

View File

@@ -11,6 +11,14 @@ import { Readable } from 'stream';
import { getPathFromAmdModule } from 'vs/base/common/amd';
suite('Encoding', () => {
test('detectBOM does not return error for non existing file', async () => {
const file = getPathFromAmdModule(require, './fixtures/not-exist.css');
const detectedEncoding = await encoding.detectEncodingByBOM(file);
assert.equal(detectedEncoding, null);
});
test('detectBOM UTF-8', async () => {
const file = getPathFromAmdModule(require, './fixtures/some_utf8.css');

View File

@@ -8,7 +8,8 @@ import { getMachineId } from 'vs/base/node/id';
suite('ID', () => {
test('getMachineId', () => {
test('getMachineId', function () {
this.timeout(20000);
return getMachineId().then(id => {
assert.ok(id);
});