Merge VS Code 1.21 source code (#1067)

* Initial VS Code 1.21 file copy with patches

* A few more merges

* Post npm install

* Fix batch of build breaks

* Fix more build breaks

* Fix more build errors

* Fix more build breaks

* Runtime fixes 1

* Get connection dialog working with some todos

* Fix a few packaging issues

* Copy several node_modules to package build to fix loader issues

* Fix breaks from master

* A few more fixes

* Make tests pass

* First pass of license header updates

* Second pass of license header updates

* Fix restore dialog issues

* Remove add additional themes menu items

* fix select box issues where the list doesn't show up

* formatting

* Fix editor dispose issue

* Copy over node modules to correct location on all platforms
This commit is contained in:
Karl Burtram
2018-04-04 15:27:51 -07:00
committed by GitHub
parent 5fba3e31b4
commit dafb780987
9412 changed files with 141255 additions and 98813 deletions

View File

@@ -10,7 +10,7 @@ import { TPromise } from 'vs/base/common/winjs.base';
import types = require('vs/base/common/types');
import URI from 'vs/base/common/uri';
import { ITree, IActionProvider } from 'vs/base/parts/tree/browser/tree';
import { IconLabel, IIconLabelOptions } from 'vs/base/browser/ui/iconLabel/iconLabel';
import { IconLabel, IIconLabelValueOptions } from 'vs/base/browser/ui/iconLabel/iconLabel';
import { IQuickNavigateConfiguration, IModel, IDataSource, IFilter, IAccessiblityProvider, IRenderer, IRunner, Mode } from 'vs/base/parts/quickopen/common/quickOpen';
import { Action, IAction, IActionRunner } from 'vs/base/common/actions';
import { compareAnything } from 'vs/base/common/comparers';
@@ -84,7 +84,7 @@ export class QuickOpenEntry {
/**
* The options for the label to use for this entry
*/
public getLabelOptions(): IIconLabelOptions {
public getLabelOptions(): IIconLabelValueOptions {
return null;
}
@@ -116,6 +116,20 @@ export class QuickOpenEntry {
return null;
}
/**
* A tooltip to show when hovering over the entry.
*/
public getTooltip(): string {
return null;
}
/**
* A tooltip to show when hovering over the description portion of the entry.
*/
public getDescriptionTooltip(): string {
return null;
}
/**
* An optional keybinding to show for an entry.
*/
@@ -171,8 +185,13 @@ export class QuickOpenEntry {
return false;
}
public isFile(): boolean {
return false; // TODO@Ben debt with editor history merging
/**
* Determines if this quick open entry should merge with the editor history in quick open. If set to true
* and the resource of this entry is the same as the resource for an editor history, it will not show up
* because it is considered to be a duplicate of an editor history.
*/
public mergeWithEditorHistory(): boolean {
return false;
}
}
@@ -215,7 +234,7 @@ export class QuickOpenEntryGroup extends QuickOpenEntry {
return this.entry ? this.entry.getLabel() : super.getLabel();
}
public getLabelOptions(): IIconLabelOptions {
public getLabelOptions(): IIconLabelValueOptions {
return this.entry ? this.entry.getLabelOptions() : super.getLabelOptions();
}
@@ -293,7 +312,6 @@ export interface IQuickOpenEntryTemplateData {
icon: HTMLSpanElement;
label: IconLabel;
detail: HighlightedLabel;
description: HighlightedLabel;
keybinding: KeybindingLabel;
actionBar: ActionBar;
}
@@ -347,13 +365,7 @@ class Renderer implements IRenderer<QuickOpenEntry> {
row1.appendChild(icon);
// Label
const label = new IconLabel(row1, { supportHighlights: true });
// Description
const descriptionContainer = document.createElement('span');
row1.appendChild(descriptionContainer);
DOM.addClass(descriptionContainer, 'quick-open-entry-description');
const description = new HighlightedLabel(descriptionContainer);
const label = new IconLabel(row1, { supportHighlights: true, supportDescriptionHighlights: true });
// Keybinding
const keybindingContainer = document.createElement('span');
@@ -392,15 +404,13 @@ class Renderer implements IRenderer<QuickOpenEntry> {
icon,
label,
detail,
description,
keybinding,
group,
actionBar
};
}
public renderElement(entry: QuickOpenEntry, templateId: string, templateData: any, styles: IQuickOpenStyles): void {
const data: IQuickOpenEntryTemplateData = templateData;
public renderElement(entry: QuickOpenEntry, templateId: string, data: IQuickOpenEntryGroupTemplateData, styles: IQuickOpenStyles): void {
// Action Bar
if (this.actionProvider.hasActions(null, entry)) {
@@ -412,8 +422,6 @@ class Renderer implements IRenderer<QuickOpenEntry> {
data.actionBar.context = entry; // make sure the context is the current element
this.actionProvider.getActions(null, entry).then((actions) => {
// TODO@Ben this will not work anymore as soon as quick open has more actions
// but as long as there is only one are ok
if (data.actionBar.isEmpty() && actions && actions.length > 0) {
data.actionBar.push(actions, { icon: true, label: false });
} else if (!data.actionBar.isEmpty() && (!actions || actions.length === 0)) {
@@ -431,7 +439,7 @@ class Renderer implements IRenderer<QuickOpenEntry> {
// Entry group
if (entry instanceof QuickOpenEntryGroup) {
const group = <QuickOpenEntryGroup>entry;
const groupData = <IQuickOpenEntryGroupTemplateData>templateData;
const groupData = data;
// Border
if (group.showBorder()) {
@@ -457,30 +465,27 @@ class Renderer implements IRenderer<QuickOpenEntry> {
data.icon.className = iconClass;
// Label
const options: IIconLabelOptions = entry.getLabelOptions() || Object.create(null);
const options: IIconLabelValueOptions = entry.getLabelOptions() || Object.create(null);
options.matches = labelHighlights || [];
data.label.setValue(entry.getLabel(), null, options);
options.title = entry.getTooltip();
options.descriptionTitle = entry.getDescriptionTooltip() || entry.getDescription(); // tooltip over description because it could overflow
options.descriptionMatches = descriptionHighlights || [];
data.label.setValue(entry.getLabel(), entry.getDescription(), options);
// Meta
data.detail.set(entry.getDetail(), detailHighlights);
// Description
data.description.set(entry.getDescription(), descriptionHighlights || []);
data.description.element.title = entry.getDescription();
// Keybinding
data.keybinding.set(entry.getKeybinding(), null);
}
}
public disposeTemplate(templateId: string, templateData: any): void {
public disposeTemplate(templateId: string, templateData: IQuickOpenEntryGroupTemplateData): void {
const data = templateData as IQuickOpenEntryGroupTemplateData;
data.actionBar.dispose();
data.actionBar = null;
data.container = null;
data.entry = null;
data.description.dispose();
data.description = null;
data.keybinding.dispose();
data.keybinding = null;
data.detail.dispose();

View File

@@ -26,6 +26,7 @@ import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
import { Color } from 'vs/base/common/color';
import { mixin } from 'vs/base/common/objects';
import { StandardMouseEvent } from 'vs/base/browser/mouseEvent';
export interface IQuickOpenCallbacks {
onOk: () => void;
@@ -154,8 +155,8 @@ export class QuickOpenWidget implements IModelProvider {
}
})
.on(DOM.EventType.CONTEXT_MENU, (e: Event) => DOM.EventHelper.stop(e, true)) // Do this to fix an issue on Mac where the menu goes into the way
.on(DOM.EventType.FOCUS, (e: Event) => this.gainingFocus(), null, true)
.on(DOM.EventType.BLUR, (e: Event) => this.loosingFocus(e), null, true);
.on(DOM.EventType.FOCUS, (e: FocusEvent) => this.gainingFocus(), null, true)
.on(DOM.EventType.BLUR, (e: FocusEvent) => this.loosingFocus(e), null, true);
// Progress Bar
this.progressBar = new ProgressBar(div.clone(), { progressBarBackground: this.styles.progressBarBackground });
@@ -253,7 +254,10 @@ export class QuickOpenWidget implements IModelProvider {
this.toUnbind.push(this.tree.onDidChangeSelection((event: ISelectionEvent) => {
if (event.selection && event.selection.length > 0) {
this.elementSelected(event.selection[0], event);
const mouseEvent: StandardMouseEvent = event.payload && event.payload.originalEvent instanceof StandardMouseEvent ? event.payload.originalEvent : void 0;
const shouldOpenInBackground = mouseEvent ? this.shouldOpenInBackground(mouseEvent) : false;
this.elementSelected(event.selection[0], event, shouldOpenInBackground ? Mode.OPEN_IN_BACKGROUND : Mode.OPEN);
}
}));
}).
@@ -399,19 +403,26 @@ export class QuickOpenWidget implements IModelProvider {
}
}
private shouldOpenInBackground(e: StandardKeyboardEvent): boolean {
if (e.keyCode !== KeyCode.RightArrow) {
return false; // only for right arrow
private shouldOpenInBackground(e: StandardKeyboardEvent | StandardMouseEvent): boolean {
// Keyboard
if (e instanceof StandardKeyboardEvent) {
if (e.keyCode !== KeyCode.RightArrow) {
return false; // only for right arrow
}
if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) {
return false; // no modifiers allowed
}
// validate the cursor is at the end of the input and there is no selection,
// and if not prevent opening in the background such as the selection can be changed
const element = this.inputBox.inputElement;
return element.selectionEnd === this.inputBox.value.length && element.selectionStart === element.selectionEnd;
}
if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) {
return false; // no modifiers allowed
}
// validate the cursor is at the end of the input and there is no selection,
// and if not prevent opening in the background such as the selection can be changed
const element = this.inputBox.inputElement;
return element.selectionEnd === this.inputBox.value.length && element.selectionStart === element.selectionEnd;
// Mouse
return e.middleButton;
}
private onType(): void {
@@ -931,12 +942,12 @@ export class QuickOpenWidget implements IModelProvider {
this.isLoosingFocus = false;
}
private loosingFocus(e: Event): void {
private loosingFocus(e: FocusEvent): void {
if (!this.isVisible()) {
return;
}
const relatedTarget = (<any>e).relatedTarget;
const relatedTarget = e.relatedTarget as HTMLElement;
if (!this.quickNavigateConfiguration && DOM.isAncestor(relatedTarget, this.builder.getHTMLElement())) {
return; // user clicked somewhere into quick open widget, do not close thereby
}

View File

@@ -70,6 +70,11 @@
flex-shrink: 0;
}
.quick-open-widget .quick-open-tree .monaco-icon-label,
.quick-open-widget .quick-open-tree .monaco-icon-label .monaco-icon-label-description-container {
flex: 1; /* make sure the icon label grows within the row */
}
.quick-open-widget .quick-open-tree .quick-open-entry .monaco-highlighted-label span {
opacity: 1;
}
@@ -79,15 +84,6 @@
line-height: normal;
}
.quick-open-widget .quick-open-tree .quick-open-entry-description {
opacity: 0.7;
margin-left: 0.5em;
font-size: 0.9em;
overflow: hidden;
flex: 1;
text-overflow: ellipsis;
}
.quick-open-widget .quick-open-tree .content.has-group-label .quick-open-entry-keybinding {
margin-right: 8px;
}

View File

@@ -87,10 +87,10 @@ function doScore(query: string, queryLower: string, queryLength: number, target:
const leftIndex = currentIndex - 1;
const diagIndex = (queryIndex - 1) * targetLength + targetIndex - 1;
const leftScore = targetIndex > 0 ? scores[leftIndex] : 0;
const diagScore = queryIndex > 0 && targetIndex > 0 ? scores[diagIndex] : 0;
const leftScore: number = targetIndex > 0 ? scores[leftIndex] : 0;
const diagScore: number = queryIndex > 0 && targetIndex > 0 ? scores[diagIndex] : 0;
const matchesSequenceLength = queryIndex > 0 && targetIndex > 0 ? matches[diagIndex] : 0;
const matchesSequenceLength: number = queryIndex > 0 && targetIndex > 0 ? matches[diagIndex] : 0;
// If we are not matching on the first query character any more, we only produce a
// score if we had a score previously for the last query index (by looking at the diagScore).
@@ -296,6 +296,7 @@ const LABEL_CAMELCASE_SCORE = 1 << 16;
const LABEL_SCORE_THRESHOLD = 1 << 15;
export interface IPreparedQuery {
original: string;
value: string;
lowercase: string;
containsPathSeparator: boolean;
@@ -304,12 +305,13 @@ export interface IPreparedQuery {
/**
* Helper function to prepare a search value for scoring in quick open by removing unwanted characters.
*/
export function prepareQuery(value: string): IPreparedQuery {
export function prepareQuery(original: string): IPreparedQuery {
let lowercase: string;
let containsPathSeparator: boolean;
let value: string;
if (value) {
value = stripWildcards(value).replace(/\s/g, ''); // get rid of all wildcards and whitespace
if (original) {
value = stripWildcards(original).replace(/\s/g, ''); // get rid of all wildcards and whitespace
if (isWindows) {
value = value.replace(/\//g, '\\'); // Help Windows users to search for paths when using slash
}
@@ -318,7 +320,7 @@ export function prepareQuery(value: string): IPreparedQuery {
containsPathSeparator = value.indexOf(nativeSep) >= 0;
}
return { value, lowercase, containsPathSeparator };
return { original, value, lowercase, containsPathSeparator };
}
export function scoreItem<T>(item: T, query: IPreparedQuery, fuzzy: boolean, accessor: IItemAccessor<T>, cache: ScorerCache): IItemScore {
@@ -354,7 +356,7 @@ export function scoreItem<T>(item: T, query: IPreparedQuery, fuzzy: boolean, acc
function doScoreItem(label: string, description: string, path: string, query: IPreparedQuery, fuzzy: boolean): IItemScore {
// 1.) treat identity matches on full path highest
if (path && isEqual(query.value, path, true)) {
if (path && isEqual(query.original, path, true)) {
return { score: PATH_IDENTITY_SCORE, labelMatch: [{ start: 0, end: label.length }], descriptionMatch: description ? [{ start: 0, end: description.length }] : void 0 };
}

View File

@@ -38,8 +38,14 @@ export enum ClickBehavior {
ON_MOUSE_UP
}
export enum OpenMode {
SINGLE_CLICK,
DOUBLE_CLICK
}
export interface IControllerOptions {
clickBehavior?: ClickBehavior;
openMode?: OpenMode;
keyboardSupport?: boolean;
}
@@ -82,7 +88,7 @@ export class DefaultController implements _.IController {
private options: IControllerOptions;
constructor(options: IControllerOptions = { clickBehavior: ClickBehavior.ON_MOUSE_UP, keyboardSupport: true }) {
constructor(options: IControllerOptions = { clickBehavior: ClickBehavior.ON_MOUSE_DOWN, keyboardSupport: true, openMode: OpenMode.SINGLE_CLICK }) {
this.options = options;
this.downKeyBindingDispatcher = new KeybindingDispatcher();
@@ -153,12 +159,14 @@ export class DefaultController implements _.IController {
protected onLeftClick(tree: _.ITree, element: any, eventish: ICancelableEvent, origin: string = 'mouse'): boolean {
const payload = { origin: origin, originalEvent: eventish };
const event = <mouse.IMouseEvent>eventish;
const isDoubleClick = (origin === 'mouse' && event.detail === 2);
if (tree.getInput() === element) {
tree.clearFocus(payload);
tree.clearSelection(payload);
} else {
const isMouseDown = eventish && (<mouse.IMouseEvent>eventish).browserEvent && (<mouse.IMouseEvent>eventish).browserEvent.type === 'mousedown';
const isMouseDown = eventish && event.browserEvent && event.browserEvent.type === 'mousedown';
if (!isMouseDown) {
eventish.preventDefault(); // we cannot preventDefault onMouseDown because this would break DND otherwise
}
@@ -168,16 +176,36 @@ export class DefaultController implements _.IController {
tree.setSelection([element], payload);
tree.setFocus(element, payload);
if (tree.isExpanded(element)) {
tree.collapse(element).done(null, errors.onUnexpectedError);
} else {
tree.expand(element).done(null, errors.onUnexpectedError);
if (this.openOnSingleClick || isDoubleClick || this.isClickOnTwistie(event)) {
if (tree.isExpanded(element)) {
tree.collapse(element).done(null, errors.onUnexpectedError);
} else {
tree.expand(element).done(null, errors.onUnexpectedError);
}
}
}
return true;
}
protected setOpenMode(openMode: OpenMode) {
this.options.openMode = openMode;
}
protected get openOnSingleClick(): boolean {
return this.options.openMode === OpenMode.SINGLE_CLICK;
}
protected isClickOnTwistie(event: mouse.IMouseEvent): boolean {
const target = event.target as HTMLElement;
// There is no way to find out if the ::before element is clicked where
// the twistie is drawn, but the <div class="content"> element in the
// tree item is the only thing we get back as target when the user clicks
// on the twistie.
return target && target.className === 'content' && dom.hasClass(target.parentElement, 'monaco-tree-row');
}
public onContextMenu(tree: _.ITree, element: any, event: _.ContextMenuEvent): boolean {
if (event.target && event.target.tagName && event.target.tagName.toLowerCase() === 'input') {
return false; // allow context menu on input fields

View File

@@ -6,10 +6,6 @@
import _ = require('vs/base/parts/tree/browser/tree');
import Mouse = require('vs/base/browser/mouseEvent');
import { DefaultDragAndDrop } from 'vs/base/parts/tree/browser/treeDefaults';
import URI from 'vs/base/common/uri';
import { basename } from 'vs/base/common/paths';
import { getPathLabel } from 'vs/base/common/labels';
export class ElementsDragAndDropData implements _.IDragAndDropData {
@@ -75,48 +71,4 @@ export class DesktopDragAndDropData implements _.IDragAndDropData {
files: this.files
};
}
}
export class SimpleFileResourceDragAndDrop extends DefaultDragAndDrop {
constructor(private toResource: (obj: any) => URI) {
super();
}
public getDragURI(tree: _.ITree, obj: any): string {
const resource = this.toResource(obj);
if (resource) {
return resource.toString();
}
return void 0;
}
public getDragLabel(tree: _.ITree, elements: any[]): string {
if (elements.length > 1) {
return String(elements.length);
}
const resource = this.toResource(elements[0]);
if (resource) {
return basename(resource.fsPath);
}
return void 0;
}
public onDragStart(tree: _.ITree, data: _.IDragAndDropData, originalEvent: Mouse.DragMouseEvent): void {
const sources: object[] = data.getData();
let source: object = null;
if (sources.length > 0) {
source = sources[0];
}
// Apply some datatransfer types to allow for dragging the element outside of the application
const resource = this.toResource(source);
if (resource) {
originalEvent.dataTransfer.setData('text/plain', getPathLabel(resource));
}
}
}

View File

@@ -24,6 +24,7 @@ import _ = require('vs/base/parts/tree/browser/tree');
import { KeyCode } from 'vs/base/common/keyCodes';
import Event, { Emitter } from 'vs/base/common/event';
import { IDomNodePagePosition } from 'vs/base/browser/dom';
import { DataTransfers } from 'vs/base/browser/dnd';
export interface IRow {
element: HTMLElement;
@@ -825,7 +826,7 @@ export class TreeView extends HeightMap {
public getScrollPosition(): number {
const height = this.getTotalHeight() - this.viewHeight;
return height <= 0 ? 0 : this.scrollTop / height;
return height <= 0 ? 1 : this.scrollTop / height;
}
public setScrollPosition(pos: number): void {
@@ -1291,7 +1292,7 @@ export class TreeView extends HeightMap {
}
e.dataTransfer.effectAllowed = 'copyMove';
e.dataTransfer.setData('URL', item.uri);
e.dataTransfer.setData(DataTransfers.RESOURCES, JSON.stringify([item.uri]));
if (e.dataTransfer.setDragImage) {
let label: string;
@@ -1658,4 +1659,4 @@ export class TreeView extends HeightMap {
super.dispose();
}
}
}