From 891b8c0bf0b747170ffe35e22b61f6db3b78277b Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 19 Apr 2016 12:31:10 -0700 Subject: [PATCH 001/297] Integrated terminal prototype Part of #143 --- package.json | 2 + .../parts/terminal/common/terminal.ts | 20 +++++ .../node/media/terminal.contribution.css | 43 +++++++++ .../workbench/parts/terminal/node/pty.js.d.ts | 16 ++++ .../parts/terminal/node/term.js.d.ts | 17 ++++ .../terminal/node/terminal.contribution.ts | 51 +++++++++++ .../parts/terminal/node/terminalActions.ts | 37 ++++++++ .../parts/terminal/node/terminalPanel.ts | 89 +++++++++++++++++++ .../parts/terminal/node/terminalService.ts | 21 +++++ src/vs/workbench/workbench.main.js | 2 + 10 files changed, 298 insertions(+) create mode 100644 src/vs/workbench/parts/terminal/common/terminal.ts create mode 100644 src/vs/workbench/parts/terminal/node/media/terminal.contribution.css create mode 100644 src/vs/workbench/parts/terminal/node/pty.js.d.ts create mode 100644 src/vs/workbench/parts/terminal/node/term.js.d.ts create mode 100644 src/vs/workbench/parts/terminal/node/terminal.contribution.ts create mode 100644 src/vs/workbench/parts/terminal/node/terminalActions.ts create mode 100644 src/vs/workbench/parts/terminal/node/terminalPanel.ts create mode 100644 src/vs/workbench/parts/terminal/node/terminalService.ts diff --git a/package.json b/package.json index 4a72af69404..40770133839 100644 --- a/package.json +++ b/package.json @@ -26,8 +26,10 @@ "https-proxy-agent": "^0.3.5", "iconv-lite": "^0.4.13", "native-keymap": "^0.1.2", + "pty.js": "^0.3.0", "sax": "^1.1.1", "semver": "^4.2.0", + "term.js": "0.0.7", "vscode-debugprotocol": "1.8.0-pre.3", "vscode-textmate": "^1.0.11", "winreg": "0.0.12", diff --git a/src/vs/workbench/parts/terminal/common/terminal.ts b/src/vs/workbench/parts/terminal/common/terminal.ts new file mode 100644 index 00000000000..9fbb0644ecd --- /dev/null +++ b/src/vs/workbench/parts/terminal/common/terminal.ts @@ -0,0 +1,20 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +import {TPromise} from 'vs/base/common/winjs.base'; +import {createDecorator, ServiceIdentifier} from 'vs/platform/instantiation/common/instantiation'; + +export const TERMINAL_PANEL_ID = 'workbench.panel.terminal'; + +export const TERMINAL_SERVICE_ID = 'terminalService'; + +export var ITerminalService = createDecorator(TERMINAL_SERVICE_ID); + +export interface ITerminalService { + serviceId: ServiceIdentifier; + + show(): TPromise; +} diff --git a/src/vs/workbench/parts/terminal/node/media/terminal.contribution.css b/src/vs/workbench/parts/terminal/node/media/terminal.contribution.css new file mode 100644 index 00000000000..ed76aefc063 --- /dev/null +++ b/src/vs/workbench/parts/terminal/node/media/terminal.contribution.css @@ -0,0 +1,43 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +.monaco-workbench .integrated-terminal { + align-items: flex-end; + display: flex; +} + +.monaco-workbench .integrated-terminal .terminal { + background-color: #1e1e1e!important; +} + +.monaco-workbench .terminal-cursor { + background-color: #1e1e1e; +} + +.monaco-workbench .reverse-video { + color: #CCC; +} + +.vs-dark .monaco-workbench .terminal-cursor { + background-color: #CCC; +} + +.vs-dark .monaco-workbench .reverse-video { + color: #252526; +} + +/* High Contrast Theming */ + +.hc-dark .monaco-workbench .integrated-terminal .terminal { + background-color: black!important; +} + +.hc-dark .monaco-workbench .terminal-cursor { + background-color: white; +} + +.hc-dark .monaco-workbench .reverse-video { + color: black; +} \ No newline at end of file diff --git a/src/vs/workbench/parts/terminal/node/pty.js.d.ts b/src/vs/workbench/parts/terminal/node/pty.js.d.ts new file mode 100644 index 00000000000..0c44c428c51 --- /dev/null +++ b/src/vs/workbench/parts/terminal/node/pty.js.d.ts @@ -0,0 +1,16 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +declare module 'pty.js' { + export function fork(file: string, args: string[], options: any): Terminal; + export function spawn(file: string, args: string[], options: any): Terminal; + export function createTerminal(file: string, args: string[], options: any): Terminal; + + export interface Terminal { + on(event: string, callback: (data: any) => void): void; + resize(columns: number, rows: number): void; + write(data: string): void; + } +} \ No newline at end of file diff --git a/src/vs/workbench/parts/terminal/node/term.js.d.ts b/src/vs/workbench/parts/terminal/node/term.js.d.ts new file mode 100644 index 00000000000..9f2c4c7ea9e --- /dev/null +++ b/src/vs/workbench/parts/terminal/node/term.js.d.ts @@ -0,0 +1,17 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +declare module 'term.js' { + function init(): TermJsTerminal; + + // There seems to be no way to export this so it can be referenced outside of this file when a + // module is a function. + interface TermJsTerminal { + on(event: string, callback: (data: any) => void): void; + resize(columns: number, rows: number): void; + } + + export = init; +} \ No newline at end of file diff --git a/src/vs/workbench/parts/terminal/node/terminal.contribution.ts b/src/vs/workbench/parts/terminal/node/terminal.contribution.ts new file mode 100644 index 00000000000..3360a59d19a --- /dev/null +++ b/src/vs/workbench/parts/terminal/node/terminal.contribution.ts @@ -0,0 +1,51 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import 'vs/css!./media/terminal.contribution'; +import nls = require('vs/nls'); +//import {KeyMod, KeyCode} from 'vs/base/common/keyCodes'; +import {SyncActionDescriptor} from 'vs/platform/actions/common/actions'; +import {registerSingleton} from 'vs/platform/instantiation/common/extensions'; +import {IWorkbenchActionRegistry, Extensions as ActionExtensions} from 'vs/workbench/common/actionRegistry'; +import {TerminalService} from 'vs/workbench/parts/terminal/node/terminalService'; +import {ToggleTerminalAction} from 'vs/workbench/parts/terminal/node/terminalActions'; +import {ITerminalService, TERMINAL_PANEL_ID} from 'vs/workbench/parts/terminal/common/terminal'; +import * as panel from 'vs/workbench/browser/panel'; +import {Registry} from 'vs/platform/platform'; +import {Extensions, IConfigurationRegistry} from 'vs/platform/configuration/common/configurationRegistry'; + +let configurationRegistry = Registry.as(Extensions.Configuration); +configurationRegistry.registerConfiguration({ + 'id': 'terminal', + 'order': 100, + 'title': nls.localize('integratedTerminalConfigurationTitle', "Integrated terminal configuration"), + 'type': 'object', + 'properties': { + 'terminal.integrated.enabled': { + 'description': nls.localize('terminal.integrated.enabled', "(Experimental) Enable the integrated terminal."), + 'type': 'boolean', + 'default': false + } + } +}); + +// Register Service +registerSingleton(ITerminalService, TerminalService); + +// Register Output Panel +(Registry.as(panel.Extensions.Panels)).registerPanel(new panel.PanelDescriptor( + 'vs/workbench/parts/terminal/node/terminalPanel', + 'TerminalPanel', + TERMINAL_PANEL_ID, + nls.localize('terminal', "Terminal"), + 'terminal' +)); + +// register toggle output action globally +let actionRegistry = Registry.as(ActionExtensions.WorkbenchActions); +/*actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ToggleTerminalAction, ToggleTerminalAction.ID, ToggleTerminalAction.LABEL, { + primary: KeyMod.CtrlCmd | KeyCode.US_BACKTICK +}), nls.localize('viewCategory', "View"));*/ +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ToggleTerminalAction, ToggleTerminalAction.ID, ToggleTerminalAction.LABEL), nls.localize('viewCategory', "View")); diff --git a/src/vs/workbench/parts/terminal/node/terminalActions.ts b/src/vs/workbench/parts/terminal/node/terminalActions.ts new file mode 100644 index 00000000000..a260a2d5a51 --- /dev/null +++ b/src/vs/workbench/parts/terminal/node/terminalActions.ts @@ -0,0 +1,37 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import {TPromise} from 'vs/base/common/winjs.base'; +import nls = require('vs/nls'); +import {Action} from 'vs/base/common/actions'; +import {IPartService} from 'vs/workbench/services/part/common/partService'; +import {IPanelService} from 'vs/workbench/services/panel/common/panelService'; +import {TERMINAL_PANEL_ID, ITerminalService} from 'vs/workbench/parts/terminal/common/terminal'; + +export class ToggleTerminalAction extends Action { + + public static ID = 'workbench.action.terminal.toggleTerminal'; + public static LABEL = nls.localize('toggleTerminal', "Toggle Terminal"); + + constructor( + id: string, label: string, + @IPartService private partService: IPartService, + @IPanelService private panelService: IPanelService, + @ITerminalService private terminalService: ITerminalService + ) { + super(id, label); + } + + public run(event?: any): TPromise { + const panel = this.panelService.getActivePanel(); + if (panel && panel.getId() === TERMINAL_PANEL_ID) { + this.partService.setPanelHidden(true); + + return TPromise.as(null); + } + + return this.terminalService.show(); + } +} \ No newline at end of file diff --git a/src/vs/workbench/parts/terminal/node/terminalPanel.ts b/src/vs/workbench/parts/terminal/node/terminalPanel.ts new file mode 100644 index 00000000000..cebb5b15bf5 --- /dev/null +++ b/src/vs/workbench/parts/terminal/node/terminalPanel.ts @@ -0,0 +1,89 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import termJs = require('term.js'); +import fs = require('fs'); +import {fork, Terminal} from 'pty.js'; +import {TPromise} from 'vs/base/common/winjs.base'; +import {Builder, Dimension} from 'vs/base/browser/builder'; +import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry'; +import {TERMINAL_PANEL_ID} from 'vs/workbench/parts/terminal/common/terminal'; +import {Panel} from 'vs/workbench/browser/panel'; +import {ScrollableElement} from 'vs/base/browser/ui/scrollbar/scrollableElementImpl'; +import {DomNodeScrollable} from 'vs/base/browser/ui/scrollbar/domNodeScrollable'; + +const TERMINAL_CHAR_WIDTH = 8; +const TERMINAL_CHAR_HEIGHT = 18; + +export class TerminalPanel extends Panel { + + private ptyProcess: Terminal; + private parentDomElement: HTMLElement; + private terminal; + private terminalDomElement: HTMLDivElement; + + constructor( + @ITelemetryService telemetryService: ITelemetryService + ) { + super(TERMINAL_PANEL_ID, telemetryService); + } + + public layout(dimension: Dimension): void { + let cols = Math.floor(this.parentDomElement.offsetWidth / TERMINAL_CHAR_WIDTH); + let rows = Math.floor(this.parentDomElement.offsetHeight / TERMINAL_CHAR_HEIGHT); + this.terminal.resize(cols, rows); + this.ptyProcess.resize(cols, rows); + } + + public create(parent: Builder): TPromise { + super.create(parent); + + this.ptyProcess = fork(process.env.SHELL || 'sh', [], { + name: fs.existsSync('/usr/share/terminfo/x/xterm-256color') ? 'xterm-256color' : 'xterm', + cols: 80, + rows: 6, + cwd: process.env.HOME + }); + this.parentDomElement = parent.getHTMLElement(); + this.terminalDomElement = document.createElement('div'); + this.parentDomElement.classList.add('integrated-terminal'); + let terminalScrollable = new DomNodeScrollable(this.terminalDomElement); + let terminalContainer = new ScrollableElement(this.terminalDomElement, terminalScrollable, { horizontal: 'hidden', vertical: 'auto' }); + this.terminal = termJs(); + + this.ptyProcess.on('data', (data) => { + this.terminal.write(data); + }); + this.terminal.on('data', (data) => { + this.ptyProcess.write(data); + return false; + }); + + this.terminal.open(this.terminalDomElement); + this.parentDomElement.appendChild(terminalContainer.getDomNode()); + + this.terminalDomElement.style.fontFamily = 'Hack, mono'; + this.terminal.colors = [ + '#000000', // black + '#cd3131', // red + '#09885a', // green + '#e5e510', // yellow + '#0451a5', // blue + '#bc05bc', // magenta + '#0598bc', // cyan + '#e5e5e5', // white + '#111111', // bright black + '#dc6f6f', // bright red + '#53ac8c', // bright green + '#eded58', // bright yellow + '#4f85c0', // bright blue + '#d050d0', // bright magenta + '#50b7d0', // bright cyan + '#FFFFFF', // bright white + ]; + + return TPromise.as(null); + } +} diff --git a/src/vs/workbench/parts/terminal/node/terminalService.ts b/src/vs/workbench/parts/terminal/node/terminalService.ts new file mode 100644 index 00000000000..7d5c3837d96 --- /dev/null +++ b/src/vs/workbench/parts/terminal/node/terminalService.ts @@ -0,0 +1,21 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import {TPromise} from 'vs/base/common/winjs.base'; +import {IPanelService} from 'vs/workbench/services/panel/common/panelService'; +import {ITerminalService, TERMINAL_PANEL_ID} from 'vs/workbench/parts/terminal/common/terminal'; + +export class TerminalService implements ITerminalService { + public serviceId = ITerminalService; + + constructor( + @IPanelService private panelService: IPanelService + ) { + } + + public show(): TPromise { + return this.panelService.openPanel(TERMINAL_PANEL_ID, true); + } +} \ No newline at end of file diff --git a/src/vs/workbench/workbench.main.js b/src/vs/workbench/workbench.main.js index ffa5618f20c..77b25bd7d31 100644 --- a/src/vs/workbench/workbench.main.js +++ b/src/vs/workbench/workbench.main.js @@ -58,6 +58,8 @@ define([ 'vs/workbench/parts/output/browser/output.contribution', + 'vs/workbench/parts/terminal/node/terminal.contribution', + 'vs/workbench/parts/markdown/browser/markdown.contribution', 'vs/workbench/parts/markdown/browser/markdownActions.contribution', From ae6bc331969c94ae2df0ff2d7aad3ecfdb4d615f Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 19 Apr 2016 14:09:59 -0700 Subject: [PATCH 002/297] Set dep to pty.js@0.3.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6cd11bdafee..6c9fe0fbfda 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "https-proxy-agent": "0.3.6", "iconv-lite": "0.4.13", "native-keymap": "0.1.2", - "pty.js": "^0.3.0", + "pty.js": "0.3.0", "sax": "1.1.2", "semver": "4.3.6", "term.js": "0.0.7", From 5939b5c17b238de302e1a9694ded55d53aaebb1f Mon Sep 17 00:00:00 2001 From: IOKLO Date: Mon, 18 Apr 2016 01:56:26 +0900 Subject: [PATCH 003/297] fix Korean(and Chinese, Japanese) IME behavior - fix displaying Korean letters twice during composition - show composition letters between the text not over the text --- src/vs/base/browser/compositionEvent.ts | 11 +++++ .../browser/controller/keyboardHandler.ts | 45 ++++++++++++++----- .../common/controller/textAreaHandler.ts | 41 +++++++++++++---- .../editor/common/controller/textAreaState.ts | 21 ++++++++- .../test/common/mocks/mockTextAreaWrapper.ts | 12 +++-- 5 files changed, 105 insertions(+), 25 deletions(-) create mode 100644 src/vs/base/browser/compositionEvent.ts diff --git a/src/vs/base/browser/compositionEvent.ts b/src/vs/base/browser/compositionEvent.ts new file mode 100644 index 00000000000..a75749721f8 --- /dev/null +++ b/src/vs/base/browser/compositionEvent.ts @@ -0,0 +1,11 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +export interface ICompositionEvent { + data: string; + locale: string; +} \ No newline at end of file diff --git a/src/vs/editor/browser/controller/keyboardHandler.ts b/src/vs/editor/browser/controller/keyboardHandler.ts index dc0f6434a09..cc4138df46e 100644 --- a/src/vs/editor/browser/controller/keyboardHandler.ts +++ b/src/vs/editor/browser/controller/keyboardHandler.ts @@ -9,6 +9,7 @@ import {Disposable, IDisposable, dispose} from 'vs/base/common/lifecycle'; import * as browser from 'vs/base/browser/browser'; import * as dom from 'vs/base/browser/dom'; import {IKeyboardEvent} from 'vs/base/browser/keyboardEvent'; +import {ICompositionEvent} from 'vs/base/browser/compositionEvent'; import {StyleMutator} from 'vs/base/browser/styleMutator'; import {GlobalScreenReaderNVDA} from 'vs/editor/common/config/commonEditorConfig'; import {TextAreaHandler} from 'vs/editor/common/controller/textAreaHandler'; @@ -104,11 +105,14 @@ class TextAreaWrapper extends Disposable implements ITextAreaWrapper { private _onKeyPress = this._register(new Emitter()); public onKeyPress: Event = this._onKeyPress.event; - private _onCompositionStart = this._register(new Emitter()); - public onCompositionStart: Event = this._onCompositionStart.event; + private _onCompositionStart = this._register(new Emitter()); + public onCompositionStart: Event = this._onCompositionStart.event; - private _onCompositionEnd = this._register(new Emitter()); - public onCompositionEnd: Event = this._onCompositionEnd.event; + private _onCompositionUpdate = this._register(new Emitter()); + public onCompositionUpdate: Event = this._onCompositionUpdate.event; + + private _onCompositionEnd = this._register(new Emitter()); + public onCompositionEnd: Event = this._onCompositionEnd.event; private _onInput = this._register(new Emitter()); public onInput: Event = this._onInput.event; @@ -129,8 +133,9 @@ class TextAreaWrapper extends Disposable implements ITextAreaWrapper { this._register(dom.addStandardDisposableListener(this._textArea, 'keydown', (e) => this._onKeyDown.fire(new KeyboardEventWrapper(e)))); this._register(dom.addStandardDisposableListener(this._textArea, 'keyup', (e) => this._onKeyUp.fire(new KeyboardEventWrapper(e)))); this._register(dom.addStandardDisposableListener(this._textArea, 'keypress', (e) => this._onKeyPress.fire(new KeyboardEventWrapper(e)))); - this._register(dom.addDisposableListener(this._textArea, 'compositionstart', (e) => this._onCompositionStart.fire())); - this._register(dom.addDisposableListener(this._textArea, 'compositionend', (e) => this._onCompositionEnd.fire())); + this._register(dom.addDisposableListener(this._textArea, 'compositionstart', (e) => this._onCompositionStart.fire(e))); + this._register(dom.addDisposableListener(this._textArea, 'compositionupdate', (e) => this._onCompositionUpdate.fire(e))); + this._register(dom.addDisposableListener(this._textArea, 'compositionend', (e) => this._onCompositionEnd.fire(e))); this._register(dom.addDisposableListener(this._textArea, 'input', (e) => this._onInput.fire())); this._register(dom.addDisposableListener(this._textArea, 'cut', (e:ClipboardEvent) => this._onCut.fire(new ClipboardEventWrapper(e)))); this._register(dom.addDisposableListener(this._textArea, 'copy', (e:ClipboardEvent) => this._onCopy.fire(new ClipboardEventWrapper(e)))); @@ -203,6 +208,8 @@ export class KeyboardHandler extends ViewEventHandler implements IDisposable { private contentWidth:number; private scrollLeft:number; + private visibleRange:editorCommon.VisibleRange; + constructor(context:IViewContext, viewController:IViewController, viewHelper:IKeyboardHandlerHelper) { super(); @@ -241,11 +248,11 @@ export class KeyboardHandler extends ViewEventHandler implements IDisposable { this.context.privateViewEventBus.emit(editorCommon.ViewEventNames.RevealRangeEvent, revealPositionEvent); // Find range pixel position - let visibleRange = this.viewHelper.visibleRangeForPositionRelativeToEditor(lineNumber, column); + this.visibleRange = this.viewHelper.visibleRangeForPositionRelativeToEditor(lineNumber, column); - if (visibleRange) { - StyleMutator.setTop(this.textArea.actual, visibleRange.top); - StyleMutator.setLeft(this.textArea.actual, this.contentLeft + visibleRange.left - this.scrollLeft); + if (this.visibleRange) { + StyleMutator.setTop(this.textArea.actual, this.visibleRange.top); + StyleMutator.setLeft(this.textArea.actual, this.contentLeft + this.visibleRange.left - this.scrollLeft); } if (browser.isIE11orEarlier) { @@ -256,12 +263,25 @@ export class KeyboardHandler extends ViewEventHandler implements IDisposable { StyleMutator.setHeight(this.textArea.actual, this.context.configuration.editor.lineHeight); dom.addClass(this.viewHelper.viewDomNode, 'ime-input'); })); + + this._toDispose.push(this.textAreaHandler.onCompositionUpdate((e) => { + + // adjust width by its size + let canvasElem = document.createElement('canvas'); + let context = canvasElem.getContext('2d'); + context.font = window.getComputedStyle(this.textArea.actual).font; + let metrics = context.measureText(e.data); + StyleMutator.setWidth(this.textArea.actual, metrics.width); + })); + this._toDispose.push(this.textAreaHandler.onCompositionEnd((e) => { this.textArea.actual.style.height = ''; this.textArea.actual.style.width = ''; StyleMutator.setLeft(this.textArea.actual, 0); StyleMutator.setTop(this.textArea.actual, 0); dom.removeClass(this.viewHelper.viewDomNode, 'ime-input'); + + this.visibleRange = null; })); this._toDispose.push(GlobalScreenReaderNVDA.onChange((value) => { this.textAreaHandler.setStrategy(this._getStrategy()); @@ -302,8 +322,13 @@ export class KeyboardHandler extends ViewEventHandler implements IDisposable { return false; } + public onScrollChanged(e:editorCommon.IScrollEvent): boolean { this.scrollLeft = e.scrollLeft; + if (this.visibleRange) { + StyleMutator.setTop(this.textArea.actual, this.visibleRange.top); + StyleMutator.setLeft(this.textArea.actual, this.contentLeft + this.visibleRange.left - this.scrollLeft); + } return false; } diff --git a/src/vs/editor/common/controller/textAreaHandler.ts b/src/vs/editor/common/controller/textAreaHandler.ts index e79ba12a90e..91f83298199 100644 --- a/src/vs/editor/common/controller/textAreaHandler.ts +++ b/src/vs/editor/common/controller/textAreaHandler.ts @@ -12,6 +12,7 @@ import {IClipboardEvent, IKeyboardEventWrapper, ISimpleModel, ITextAreaWrapper, import {Position} from 'vs/editor/common/core/position'; import {Range} from 'vs/editor/common/core/range'; import {EndOfLinePreference, IEditorPosition, IEditorRange} from 'vs/editor/common/editorCommon'; +import {ICompositionEvent} from 'vs/base/browser/compositionEvent'; enum ReadFromTextArea { Type, @@ -56,8 +57,11 @@ export class TextAreaHandler extends Disposable { private _onCompositionStart = this._register(new Emitter()); public onCompositionStart: Event = this._onCompositionStart.event; - private _onCompositionEnd = this._register(new Emitter()); - public onCompositionEnd: Event = this._onCompositionEnd.event; + private _onCompositionUpdate = this._register(new Emitter()); + public onCompositionUpdate: Event = this._onCompositionUpdate.event; + + private _onCompositionEnd = this._register(new Emitter()); + public onCompositionEnd: Event = this._onCompositionEnd.event; private Browser:IBrowser; private textArea:ITextAreaWrapper; @@ -108,8 +112,8 @@ export class TextAreaHandler extends Disposable { this.textareaIsShownAtCursor = false; - this._register(this.textArea.onCompositionStart(() => { - let timeSinceLastCompositionEnd = (new Date().getTime()) - this.lastCompositionEndTime; + this._register(this.textArea.onCompositionStart((e) => { + if (this.textareaIsShownAtCursor) { return; } @@ -117,7 +121,7 @@ export class TextAreaHandler extends Disposable { this.textareaIsShownAtCursor = true; // In IE we cannot set .value when handling 'compositionstart' because the entire composition will get canceled. - let shouldEmptyTextArea = (timeSinceLastCompositionEnd >= 100); + let shouldEmptyTextArea = true; if (shouldEmptyTextArea) { if (!this.Browser.isIE11orEarlier) { this.setTextAreaState('compositionstart', this.textAreaState.toEmpty()); @@ -136,13 +140,26 @@ export class TextAreaHandler extends Disposable { showAtLineNumber = this.cursorPosition.lineNumber; showAtColumn = this.cursorPosition.column; } - this._onCompositionStart.fire({ showAtLineNumber: showAtLineNumber, showAtColumn: showAtColumn }); })); + this._register(this.textArea.onCompositionUpdate((e) => { + this.textAreaState = this.textAreaState.fromText(e.data); + let typeInput = this.textAreaState.updateComposition(); + if (this._nextCommand === ReadFromTextArea.Type) { + if (typeInput.text !== '') { + this._onType.fire(typeInput); + } + } else { + this.executePaste(typeInput.text); + this._nextCommand = ReadFromTextArea.Type; + } + this._onCompositionUpdate.fire(e); + })); + let readFromTextArea = () => { this.textAreaState = this.textAreaState.fromTextArea(this.textArea); let typeInput = this.textAreaState.deduceInput(); @@ -157,9 +174,11 @@ export class TextAreaHandler extends Disposable { } }; - this._register(this.textArea.onCompositionEnd(() => { - // console.log('onCompositionEnd: ' + this.textArea.getValue()); - // readFromTextArea(); + this._register(this.textArea.onCompositionEnd((e) => { + // console.log('onCompositionEnd: ' + e.data); + this.textAreaState = this.textAreaState.fromText(e.data); + let typeInput = this.textAreaState.updateComposition(); + this._onType.fire(typeInput); this.lastCompositionEndTime = (new Date()).getTime(); if (!this.textareaIsShownAtCursor) { @@ -238,6 +257,10 @@ export class TextAreaHandler extends Disposable { this._writePlaceholderAndSelectTextArea('selection changed'); } + public getCursorPosition(): IEditorPosition { + return this.cursorPosition; + } + public setCursorPosition(primary: IEditorPosition): void { this.cursorPosition = primary; } diff --git a/src/vs/editor/common/controller/textAreaState.ts b/src/vs/editor/common/controller/textAreaState.ts index 3a404426832..be7794ed0f0 100644 --- a/src/vs/editor/common/controller/textAreaState.ts +++ b/src/vs/editor/common/controller/textAreaState.ts @@ -8,6 +8,7 @@ import Event from 'vs/base/common/event'; import {commonPrefixLength, commonSuffixLength} from 'vs/base/common/strings'; import {Range} from 'vs/editor/common/core/range'; import {EndOfLinePreference, IEditorPosition, IEditorRange, IRange} from 'vs/editor/common/editorCommon'; +import {ICompositionEvent} from 'vs/base/browser/compositionEvent'; export interface IClipboardEvent { canUseTextData(): boolean; @@ -26,8 +27,9 @@ export interface ITextAreaWrapper { onKeyDown: Event; onKeyUp: Event; onKeyPress: Event; - onCompositionStart: Event; - onCompositionEnd: Event; + onCompositionStart: Event; + onCompositionUpdate: Event; + onCompositionEnd: Event; onInput: Event; onCut: Event; onCopy: Event; @@ -105,6 +107,21 @@ export abstract class TextAreaState { public abstract fromText(text:string): TextAreaState; + public updateComposition(): ITypeData { + if (!this.previousState) { + // This is the EMPTY state + return { + text: '', + replaceCharCnt: 0 + }; + } + + return { + text: this.value, + replaceCharCnt: this.previousState.selectionEnd - this.previousState.selectionStart + }; + } + public abstract resetSelection(): TextAreaState; public getSelectionStart(): number { diff --git a/src/vs/editor/test/common/mocks/mockTextAreaWrapper.ts b/src/vs/editor/test/common/mocks/mockTextAreaWrapper.ts index 11bf927d1ea..ecb9ca85ff9 100644 --- a/src/vs/editor/test/common/mocks/mockTextAreaWrapper.ts +++ b/src/vs/editor/test/common/mocks/mockTextAreaWrapper.ts @@ -7,6 +7,7 @@ import Event, {Emitter} from 'vs/base/common/event'; import {Disposable} from 'vs/base/common/lifecycle'; import {IClipboardEvent, IKeyboardEventWrapper, ITextAreaWrapper} from 'vs/editor/common/controller/textAreaState'; +import {ICompositionEvent} from 'vs/base/browser/compositionEvent'; export class MockTextAreaWrapper extends Disposable implements ITextAreaWrapper { @@ -19,11 +20,14 @@ export class MockTextAreaWrapper extends Disposable implements ITextAreaWrapper private _onKeyPress = this._register(new Emitter()); public onKeyPress: Event = this._onKeyPress.event; - private _onCompositionStart = this._register(new Emitter()); - public onCompositionStart: Event = this._onCompositionStart.event; + private _onCompositionStart = this._register(new Emitter()); + public onCompositionStart: Event = this._onCompositionStart.event; - private _onCompositionEnd = this._register(new Emitter()); - public onCompositionEnd: Event = this._onCompositionEnd.event; + private _onCompositionUpdate = this._register(new Emitter()); + public onCompositionUpdate: Event = this._onCompositionUpdate.event; + + private _onCompositionEnd = this._register(new Emitter()); + public onCompositionEnd: Event = this._onCompositionEnd.event; private _onInput = this._register(new Emitter()); public onInput: Event = this._onInput.event; From 7d870e5721c6dafefef17dd90127f5d2caf60924 Mon Sep 17 00:00:00 2001 From: aioute Gao Date: Sun, 24 Apr 2016 07:55:03 +0900 Subject: [PATCH 004/297] Fix validatePosition related bug (https://github.com/Microsoft/vscode/issues/5704). --- src/vs/editor/common/model/textModel.ts | 23 ++++++++------- src/vs/workbench/api/node/extHostDocuments.ts | 29 ++++++++++--------- 2 files changed, 28 insertions(+), 24 deletions(-) diff --git a/src/vs/editor/common/model/textModel.ts b/src/vs/editor/common/model/textModel.ts index 44af80dd2b4..7b80aec512f 100644 --- a/src/vs/editor/common/model/textModel.ts +++ b/src/vs/editor/common/model/textModel.ts @@ -491,17 +491,20 @@ export class TextModel extends OrderGuaranteeEventEmitter implements editorCommo if (lineNumber < 1) { lineNumber = 1; - } - if (lineNumber > this._lines.length) { - lineNumber = this._lines.length; - } - - if (column < 1) { column = 1; } - var maxColumn = this.getLineMaxColumn(lineNumber); - if (column > maxColumn) { - column = maxColumn; + else if (lineNumber > this._lines.length) { + lineNumber = this._lines.length; + column = this.getLineMaxColumn(lineNumber); + } + else { + var maxColumn = this.getLineMaxColumn(lineNumber); + if (column < 1) { + column = 1; + } + else if (column > maxColumn) { + column = maxColumn; + } } return new Position(lineNumber, column); @@ -837,4 +840,4 @@ export class RawText { }); } -} \ No newline at end of file +} diff --git a/src/vs/workbench/api/node/extHostDocuments.ts b/src/vs/workbench/api/node/extHostDocuments.ts index df2d8c72622..c2b3e69ab63 100644 --- a/src/vs/workbench/api/node/extHostDocuments.ts +++ b/src/vs/workbench/api/node/extHostDocuments.ts @@ -393,24 +393,25 @@ export class ExtHostDocumentData extends MirrorModel2 { if (line < 0) { line = 0; - hasChanged = true; - } - - if (line >= this._lines.length) { - line = this._lines.length - 1; - hasChanged = true; - } - - if (character < 0) { character = 0; hasChanged = true; } - - let maxCharacter = this._lines[line].length; - if (character > maxCharacter) { - character = maxCharacter; + else if (line >= this._lines.length) { + line = this._lines.length - 1; + character = this._lines[line].length; hasChanged = true; } + else { + let maxCharacter = this._lines[line].length; + if (character < 0) { + character = 0; + hasChanged = true; + } + else if (character > maxCharacter) { + character = maxCharacter; + hasChanged = true; + } + } if (!hasChanged) { return position; @@ -673,4 +674,4 @@ export class MainThreadDocuments { } }, onUnexpectedError); } -} \ No newline at end of file +} From 49f20e3d5745c4af35072ee539a4336592daead9 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 23 Apr 2016 23:06:15 -0700 Subject: [PATCH 005/297] Support customizable integrated terminal shell --- .../parts/terminal/common/terminal.ts | 16 ++++++++++++++++ .../terminal/node/terminal.contribution.ts | 19 ++++++++++++------- .../parts/terminal/node/terminalPanel.ts | 15 +++++++++++++-- 3 files changed, 41 insertions(+), 9 deletions(-) diff --git a/src/vs/workbench/parts/terminal/common/terminal.ts b/src/vs/workbench/parts/terminal/common/terminal.ts index 9fbb0644ecd..98ed11c002c 100644 --- a/src/vs/workbench/parts/terminal/common/terminal.ts +++ b/src/vs/workbench/parts/terminal/common/terminal.ts @@ -6,13 +6,29 @@ import {TPromise} from 'vs/base/common/winjs.base'; import {createDecorator, ServiceIdentifier} from 'vs/platform/instantiation/common/instantiation'; +import path = require('path'); +import platform = require('vs/base/common/platform'); export const TERMINAL_PANEL_ID = 'workbench.panel.terminal'; export const TERMINAL_SERVICE_ID = 'terminalService'; +export const TERMINAL_DEFAULT_SHELL_UNIX_LIKE = process.env.SHELL || 'sh'; +export const TERMINAL_DEFAULT_SHELL_WINDOWS = platform.isWindows ? path.resolve(process.env.SystemRoot, 'System32', 'WindowsPowerShell', 'v1.0', 'powershell.exe') : ''; + export var ITerminalService = createDecorator(TERMINAL_SERVICE_ID); +export interface ITerminalConfiguration { + terminal: { + integrated: { + shell: { + unixLike: string, + windows: string + } + } + }; +} + export interface ITerminalService { serviceId: ServiceIdentifier; diff --git a/src/vs/workbench/parts/terminal/node/terminal.contribution.ts b/src/vs/workbench/parts/terminal/node/terminal.contribution.ts index 3360a59d19a..5380e31b95a 100644 --- a/src/vs/workbench/parts/terminal/node/terminal.contribution.ts +++ b/src/vs/workbench/parts/terminal/node/terminal.contribution.ts @@ -11,7 +11,7 @@ import {registerSingleton} from 'vs/platform/instantiation/common/extensions'; import {IWorkbenchActionRegistry, Extensions as ActionExtensions} from 'vs/workbench/common/actionRegistry'; import {TerminalService} from 'vs/workbench/parts/terminal/node/terminalService'; import {ToggleTerminalAction} from 'vs/workbench/parts/terminal/node/terminalActions'; -import {ITerminalService, TERMINAL_PANEL_ID} from 'vs/workbench/parts/terminal/common/terminal'; +import {ITerminalService, TERMINAL_PANEL_ID, TERMINAL_DEFAULT_SHELL_UNIX_LIKE, TERMINAL_DEFAULT_SHELL_WINDOWS} from 'vs/workbench/parts/terminal/common/terminal'; import * as panel from 'vs/workbench/browser/panel'; import {Registry} from 'vs/platform/platform'; import {Extensions, IConfigurationRegistry} from 'vs/platform/configuration/common/configurationRegistry'; @@ -20,13 +20,18 @@ let configurationRegistry = Registry.as(Extensions.Confi configurationRegistry.registerConfiguration({ 'id': 'terminal', 'order': 100, - 'title': nls.localize('integratedTerminalConfigurationTitle', "Integrated terminal configuration"), + 'title': nls.localize('integratedTerminalConfigurationTitle', "(Experimental) Integrated terminal configuration"), 'type': 'object', 'properties': { - 'terminal.integrated.enabled': { - 'description': nls.localize('terminal.integrated.enabled', "(Experimental) Enable the integrated terminal."), - 'type': 'boolean', - 'default': false + 'terminal.integrated.shell.unixLike': { + 'description': nls.localize('terminal.integrated.shell.unixLike', "The path to the shell the terminal uses on Unix-like systems (Linux, OS X)."), + 'type': 'string', + 'default': TERMINAL_DEFAULT_SHELL_UNIX_LIKE + }, + 'terminal.integrated.shell.windows': { + 'description': nls.localize('terminal.integrated.shell.windows', "The path to the shell the terminal uses on Windows."), + 'type': 'string', + 'default': TERMINAL_DEFAULT_SHELL_WINDOWS } } }); @@ -48,4 +53,4 @@ let actionRegistry = Registry.as(ActionExtensions.Work /*actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ToggleTerminalAction, ToggleTerminalAction.ID, ToggleTerminalAction.LABEL, { primary: KeyMod.CtrlCmd | KeyCode.US_BACKTICK }), nls.localize('viewCategory', "View"));*/ -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ToggleTerminalAction, ToggleTerminalAction.ID, ToggleTerminalAction.LABEL), nls.localize('viewCategory', "View")); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ToggleTerminalAction, ToggleTerminalAction.ID, ToggleTerminalAction.LABEL), nls.localize('viewCategory', "View"), ['terminal', 'panel']); diff --git a/src/vs/workbench/parts/terminal/node/terminalPanel.ts b/src/vs/workbench/parts/terminal/node/terminalPanel.ts index cebb5b15bf5..fcf73f783f7 100644 --- a/src/vs/workbench/parts/terminal/node/terminalPanel.ts +++ b/src/vs/workbench/parts/terminal/node/terminalPanel.ts @@ -6,10 +6,12 @@ import termJs = require('term.js'); import fs = require('fs'); import {fork, Terminal} from 'pty.js'; +import platform = require('vs/base/common/platform'); import {TPromise} from 'vs/base/common/winjs.base'; import {Builder, Dimension} from 'vs/base/browser/builder'; +import {IConfigurationService} from 'vs/platform/configuration/common/configuration'; import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry'; -import {TERMINAL_PANEL_ID} from 'vs/workbench/parts/terminal/common/terminal'; +import {ITerminalConfiguration, TERMINAL_PANEL_ID} from 'vs/workbench/parts/terminal/common/terminal'; import {Panel} from 'vs/workbench/browser/panel'; import {ScrollableElement} from 'vs/base/browser/ui/scrollbar/scrollableElementImpl'; import {DomNodeScrollable} from 'vs/base/browser/ui/scrollbar/domNodeScrollable'; @@ -25,6 +27,7 @@ export class TerminalPanel extends Panel { private terminalDomElement: HTMLDivElement; constructor( + @IConfigurationService private configurationService: IConfigurationService, @ITelemetryService telemetryService: ITelemetryService ) { super(TERMINAL_PANEL_ID, telemetryService); @@ -40,7 +43,7 @@ export class TerminalPanel extends Panel { public create(parent: Builder): TPromise { super.create(parent); - this.ptyProcess = fork(process.env.SHELL || 'sh', [], { + this.ptyProcess = fork(this.getShell(), [], { name: fs.existsSync('/usr/share/terminfo/x/xterm-256color') ? 'xterm-256color' : 'xterm', cols: 80, rows: 6, @@ -86,4 +89,12 @@ export class TerminalPanel extends Panel { return TPromise.as(null); } + + private getShell(): string { + let config = this.configurationService.getConfiguration(); + if (platform.isWindows) { + return config.terminal.integrated.shell.windows; + } + return config.terminal.integrated.shell.unixLike; + } } From 8e013351701c7835d9ed6302ea4370b46ce2987e Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 23 Apr 2016 23:39:28 -0700 Subject: [PATCH 006/297] Fix errors from merge --- .../parts/terminal/node/terminal.contribution.ts | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/vs/workbench/parts/terminal/node/terminal.contribution.ts b/src/vs/workbench/parts/terminal/node/terminal.contribution.ts index 5380e31b95a..e7af77311ca 100644 --- a/src/vs/workbench/parts/terminal/node/terminal.contribution.ts +++ b/src/vs/workbench/parts/terminal/node/terminal.contribution.ts @@ -24,12 +24,12 @@ configurationRegistry.registerConfiguration({ 'type': 'object', 'properties': { 'terminal.integrated.shell.unixLike': { - 'description': nls.localize('terminal.integrated.shell.unixLike', "The path to the shell the terminal uses on Unix-like systems (Linux, OS X)."), + 'description': nls.localize('terminal.integrated.shell.unixLike', "The path to the shell that the terminal uses on Unix-like systems (Linux, OS X)."), 'type': 'string', 'default': TERMINAL_DEFAULT_SHELL_UNIX_LIKE }, 'terminal.integrated.shell.windows': { - 'description': nls.localize('terminal.integrated.shell.windows', "The path to the shell the terminal uses on Windows."), + 'description': nls.localize('terminal.integrated.shell.windows', "The path to the shell that the terminal uses on Windows."), 'type': 'string', 'default': TERMINAL_DEFAULT_SHELL_WINDOWS } @@ -48,9 +48,7 @@ registerSingleton(ITerminalService, TerminalService); 'terminal' )); -// register toggle output action globally +// Register toggle output action globally let actionRegistry = Registry.as(ActionExtensions.WorkbenchActions); -/*actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ToggleTerminalAction, ToggleTerminalAction.ID, ToggleTerminalAction.LABEL, { - primary: KeyMod.CtrlCmd | KeyCode.US_BACKTICK -}), nls.localize('viewCategory', "View"));*/ -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ToggleTerminalAction, ToggleTerminalAction.ID, ToggleTerminalAction.LABEL), nls.localize('viewCategory', "View"), ['terminal', 'panel']); +// { primary: KeyMod.CtrlCmd | KeyCode.US_BACKTICK } +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ToggleTerminalAction, ToggleTerminalAction.ID, ToggleTerminalAction.LABEL), 'View: ToggleTerminalAction.LABEL', nls.localize('viewCategory', "View")); From fb71f0447863082eeb6b66a9a4bbb7e93bda1701 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 23 Apr 2016 23:41:27 -0700 Subject: [PATCH 007/297] Fix alias, :lipstick: --- .../parts/terminal/node/terminal.contribution.ts | 10 +++++----- .../workbench/parts/terminal/node/terminalActions.ts | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/parts/terminal/node/terminal.contribution.ts b/src/vs/workbench/parts/terminal/node/terminal.contribution.ts index e7af77311ca..5b0d300747a 100644 --- a/src/vs/workbench/parts/terminal/node/terminal.contribution.ts +++ b/src/vs/workbench/parts/terminal/node/terminal.contribution.ts @@ -23,13 +23,13 @@ configurationRegistry.registerConfiguration({ 'title': nls.localize('integratedTerminalConfigurationTitle', "(Experimental) Integrated terminal configuration"), 'type': 'object', 'properties': { - 'terminal.integrated.shell.unixLike': { - 'description': nls.localize('terminal.integrated.shell.unixLike', "The path to the shell that the terminal uses on Unix-like systems (Linux, OS X)."), + 'integratedTerminal.shell.unixLike': { + 'description': nls.localize('terminal.integrated.shell.unixLike', "The path of the shell that the terminal uses on Linux and OS X."), 'type': 'string', 'default': TERMINAL_DEFAULT_SHELL_UNIX_LIKE }, - 'terminal.integrated.shell.windows': { - 'description': nls.localize('terminal.integrated.shell.windows', "The path to the shell that the terminal uses on Windows."), + 'integratedTerminal.shell.windows': { + 'description': nls.localize('terminal.integrated.shell.windows', "The path of the shell that the terminal uses on Windows."), 'type': 'string', 'default': TERMINAL_DEFAULT_SHELL_WINDOWS } @@ -51,4 +51,4 @@ registerSingleton(ITerminalService, TerminalService); // Register toggle output action globally let actionRegistry = Registry.as(ActionExtensions.WorkbenchActions); // { primary: KeyMod.CtrlCmd | KeyCode.US_BACKTICK } -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ToggleTerminalAction, ToggleTerminalAction.ID, ToggleTerminalAction.LABEL), 'View: ToggleTerminalAction.LABEL', nls.localize('viewCategory', "View")); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ToggleTerminalAction, ToggleTerminalAction.ID, ToggleTerminalAction.LABEL), 'View: ' + ToggleTerminalAction.LABEL, nls.localize('viewCategory', "View")); diff --git a/src/vs/workbench/parts/terminal/node/terminalActions.ts b/src/vs/workbench/parts/terminal/node/terminalActions.ts index a260a2d5a51..aa332ca2234 100644 --- a/src/vs/workbench/parts/terminal/node/terminalActions.ts +++ b/src/vs/workbench/parts/terminal/node/terminalActions.ts @@ -13,7 +13,7 @@ import {TERMINAL_PANEL_ID, ITerminalService} from 'vs/workbench/parts/terminal/c export class ToggleTerminalAction extends Action { public static ID = 'workbench.action.terminal.toggleTerminal'; - public static LABEL = nls.localize('toggleTerminal', "Toggle Terminal"); + public static LABEL = nls.localize('toggleTerminal', "(Experimental) Toggle Terminal"); constructor( id: string, label: string, From 111e6153c4fa3f26762a0da08b4272d9a3216186 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sun, 24 Apr 2016 01:06:15 -0700 Subject: [PATCH 008/297] Support custom colors for ansi escape sequences --- .../parts/terminal/common/terminal.ts | 28 +++++-- .../terminal/node/terminal.contribution.ts | 84 ++++++++++++++++++- .../parts/terminal/node/terminalPanel.ts | 46 +++++----- 3 files changed, 130 insertions(+), 28 deletions(-) diff --git a/src/vs/workbench/parts/terminal/common/terminal.ts b/src/vs/workbench/parts/terminal/common/terminal.ts index 98ed11c002c..5420f41aff8 100644 --- a/src/vs/workbench/parts/terminal/common/terminal.ts +++ b/src/vs/workbench/parts/terminal/common/terminal.ts @@ -19,12 +19,28 @@ export const TERMINAL_DEFAULT_SHELL_WINDOWS = platform.isWindows ? path.resolve( export var ITerminalService = createDecorator(TERMINAL_SERVICE_ID); export interface ITerminalConfiguration { - terminal: { - integrated: { - shell: { - unixLike: string, - windows: string - } + integratedTerminal: { + shell: { + unixLike: string, + windows: string + }, + ansiColors: { + black: string, + red: string, + green: string, + yellow: string, + blue: string, + magenta: string, + cyan: string, + white: string, + brightBlack: string, + brightRed: string, + brightGreen: string, + brightYellow: string, + brightBlue: string, + brightMagenta: string, + brightCyan: string, + brightWhite: string, } }; } diff --git a/src/vs/workbench/parts/terminal/node/terminal.contribution.ts b/src/vs/workbench/parts/terminal/node/terminal.contribution.ts index 5b0d300747a..d56192488fb 100644 --- a/src/vs/workbench/parts/terminal/node/terminal.contribution.ts +++ b/src/vs/workbench/parts/terminal/node/terminal.contribution.ts @@ -24,14 +24,94 @@ configurationRegistry.registerConfiguration({ 'type': 'object', 'properties': { 'integratedTerminal.shell.unixLike': { - 'description': nls.localize('terminal.integrated.shell.unixLike', "The path of the shell that the terminal uses on Linux and OS X."), + 'description': nls.localize('integratedTerminal.shell.unixLike', "The path of the shell that the terminal uses on Linux and OS X."), 'type': 'string', 'default': TERMINAL_DEFAULT_SHELL_UNIX_LIKE }, 'integratedTerminal.shell.windows': { - 'description': nls.localize('terminal.integrated.shell.windows', "The path of the shell that the terminal uses on Windows."), + 'description': nls.localize('integratedTerminal.shell.windows', "The path of the shell that the terminal uses on Windows."), 'type': 'string', 'default': TERMINAL_DEFAULT_SHELL_WINDOWS + }, + 'integratedTerminal.ansiColors.black': { + 'description': nls.localize('integratedTerminal.ansiColors.black', "Black color for terminals that support ANSI escape sequences (format: #rrggbb)"), + 'type': 'string', + 'default': '#000000' + }, + 'integratedTerminal.ansiColors.red': { + 'description': nls.localize('integratedTerminal.ansiColors.red', "Red color for terminals that support ANSI escape sequences (format: #rrggbb)"), + 'type': 'string', + 'default': '#cd3131' + }, + 'integratedTerminal.ansiColors.green': { + 'description': nls.localize('integratedTerminal.ansiColors.green', "Green color for terminals that support ANSI escape sequences (format: #rrggbb)"), + 'type': 'string', + 'default': '#09885a' + }, + 'integratedTerminal.ansiColors.yellow': { + 'description': nls.localize('integratedTerminal.ansiColors.yellow', "Yellow color for terminals that support ANSI escape sequences (format: #rrggbb)"), + 'type': 'string', + 'default': '#e5e510' + }, + 'integratedTerminal.ansiColors.blue': { + 'description': nls.localize('integratedTerminal.ansiColors.blue', "Blue color for terminals that support ANSI escape sequences (format: #rrggbb)"), + 'type': 'string', + 'default': '#0451a5' + }, + 'integratedTerminal.ansiColors.magenta': { + 'description': nls.localize('integratedTerminal.ansiColors.magenta', "Magenta color for terminals that support ANSI escape sequences (format: #rrggbb)"), + 'type': 'string', + 'default': '#bc05bc' + }, + 'integratedTerminal.ansiColors.cyan': { + 'description': nls.localize('integratedTerminal.ansiColors.cyan', "Cyan color for terminals that support ANSI escape sequences (format: #rrggbb)"), + 'type': 'string', + 'default': '#0598bc' + }, + 'integratedTerminal.ansiColors.white': { + 'description': nls.localize('integratedTerminal.ansiColors.white', "White color for terminals that support ANSI escape sequences (format: #rrggbb)"), + 'type': 'string', + 'default': '#e5e5e5' + }, + 'integratedTerminal.ansiColors.brightBlack': { + 'description': nls.localize('integratedTerminal.ansiColors.brightBlack', "Bright black color for terminals that support ANSI escape sequences (format: #rrggbb)"), + 'type': 'string', + 'default': '#000000' + }, + 'integratedTerminal.ansiColors.brightRed': { + 'description': nls.localize('integratedTerminal.ansiColors.brightRed', "Bright red color for terminals that support ANSI escape sequences (format: #rrggbb)"), + 'type': 'string', + 'default': '#cd3131' + }, + 'integratedTerminal.ansiColors.brightGreen': { + 'description': nls.localize('integratedTerminal.ansiColors.brightGreen', "Bright green color for terminals that support ANSI escape sequences (format: #rrggbb)"), + 'type': 'string', + 'default': '#09885a' + }, + 'integratedTerminal.ansiColors.brightYellow': { + 'description': nls.localize('integratedTerminal.ansiColors.brightYellow', "Bright yellow color for terminals that support ANSI escape sequences (format: #rrggbb)"), + 'type': 'string', + 'default': '#e5e510' + }, + 'integratedTerminal.ansiColors.brightBlue': { + 'description': nls.localize('integratedTerminal.ansiColors.brightBlue', "Bright blue color for terminals that support ANSI escape sequences (format: #rrggbb)"), + 'type': 'string', + 'default': '#0451a5' + }, + 'integratedTerminal.ansiColors.brightMagenta': { + 'description': nls.localize('integratedTerminal.ansiColors.brightMagenta', "Bright magenta color for terminals that support ANSI escape sequences (format: #rrggbb)"), + 'type': 'string', + 'default': '#bc05bc' + }, + 'integratedTerminal.ansiColors.brightCyan': { + 'description': nls.localize('integratedTerminal.ansiColors.brightCyan', "Bright cyan color for terminals that support ANSI escape sequences (format: #rrggbb)"), + 'type': 'string', + 'default': '#0598bc' + }, + 'integratedTerminal.ansiColors.brightWhite': { + 'description': nls.localize('integratedTerminal.ansiColors.brightWhite', "Bright white color for terminals that support ANSI escape sequences (format: #rrggbb)"), + 'type': 'string', + 'default': '#e5e5e5' } } }); diff --git a/src/vs/workbench/parts/terminal/node/terminalPanel.ts b/src/vs/workbench/parts/terminal/node/terminalPanel.ts index fcf73f783f7..2e7f4cae0f0 100644 --- a/src/vs/workbench/parts/terminal/node/terminalPanel.ts +++ b/src/vs/workbench/parts/terminal/node/terminalPanel.ts @@ -68,24 +68,7 @@ export class TerminalPanel extends Panel { this.parentDomElement.appendChild(terminalContainer.getDomNode()); this.terminalDomElement.style.fontFamily = 'Hack, mono'; - this.terminal.colors = [ - '#000000', // black - '#cd3131', // red - '#09885a', // green - '#e5e510', // yellow - '#0451a5', // blue - '#bc05bc', // magenta - '#0598bc', // cyan - '#e5e5e5', // white - '#111111', // bright black - '#dc6f6f', // bright red - '#53ac8c', // bright green - '#eded58', // bright yellow - '#4f85c0', // bright blue - '#d050d0', // bright magenta - '#50b7d0', // bright cyan - '#FFFFFF', // bright white - ]; + this.terminal.colors = this.getTerminalColors(); return TPromise.as(null); } @@ -93,8 +76,31 @@ export class TerminalPanel extends Panel { private getShell(): string { let config = this.configurationService.getConfiguration(); if (platform.isWindows) { - return config.terminal.integrated.shell.windows; + return config.integratedTerminal.shell.windows; } - return config.terminal.integrated.shell.unixLike; + return config.integratedTerminal.shell.unixLike; + } + + private getTerminalColors(): string[] { + let config = this.configurationService.getConfiguration().integratedTerminal.ansiColors; + let colors = [ + config.black || '#000000', + config.red || '#cd3131', + config.green || '#09885a', + config.yellow || '#e5e510', + config.blue || '#0451a5', + config.magenta || '#bc05bc', + config.cyan || '#0598bc', + config.white || '#e5e5e5', + config.brightBlack || '#111111', + config.brightRed || '#dc6f6f', + config.brightGreen || '#53ac8c', + config.brightYellow || '#eded58', + config.brightBlue || '#4f85c0', + config.brightMagenta || '#d050d0', + config.brightCyan || '#50b7d0', + config.brightWhite || '#FFFFFF' + ]; + return colors; } } From a2fa0094a0800887cfc7010d79645b8f1463f535 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sun, 24 Apr 2016 01:22:15 -0700 Subject: [PATCH 009/297] Make term chars cover entire line --- .../parts/terminal/node/media/terminal.contribution.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/vs/workbench/parts/terminal/node/media/terminal.contribution.css b/src/vs/workbench/parts/terminal/node/media/terminal.contribution.css index ed76aefc063..10486b5a9bb 100644 --- a/src/vs/workbench/parts/terminal/node/media/terminal.contribution.css +++ b/src/vs/workbench/parts/terminal/node/media/terminal.contribution.css @@ -8,6 +8,10 @@ display: flex; } +.monaco-workbench .integrated-terminal .terminal span { + display: inline-block; /* make terminal characters cover height of line */ +} + .monaco-workbench .integrated-terminal .terminal { background-color: #1e1e1e!important; } From 194874bb165997d32c44841ee6c235785c63eca8 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sun, 24 Apr 2016 01:29:29 -0700 Subject: [PATCH 010/297] Remove redundant code --- .../parts/terminal/node/terminalPanel.ts | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/vs/workbench/parts/terminal/node/terminalPanel.ts b/src/vs/workbench/parts/terminal/node/terminalPanel.ts index 2e7f4cae0f0..f9f3400173e 100644 --- a/src/vs/workbench/parts/terminal/node/terminalPanel.ts +++ b/src/vs/workbench/parts/terminal/node/terminalPanel.ts @@ -84,22 +84,22 @@ export class TerminalPanel extends Panel { private getTerminalColors(): string[] { let config = this.configurationService.getConfiguration().integratedTerminal.ansiColors; let colors = [ - config.black || '#000000', - config.red || '#cd3131', - config.green || '#09885a', - config.yellow || '#e5e510', - config.blue || '#0451a5', - config.magenta || '#bc05bc', - config.cyan || '#0598bc', - config.white || '#e5e5e5', - config.brightBlack || '#111111', - config.brightRed || '#dc6f6f', - config.brightGreen || '#53ac8c', - config.brightYellow || '#eded58', - config.brightBlue || '#4f85c0', - config.brightMagenta || '#d050d0', - config.brightCyan || '#50b7d0', - config.brightWhite || '#FFFFFF' + config.black, + config.red, + config.green, + config.yellow, + config.blue, + config.magenta, + config.cyan, + config.white, + config.brightBlack, + config.brightRed, + config.brightGreen, + config.brightYellow, + config.brightBlue, + config.brightMagenta, + config.brightCyan, + config.brightWhite ]; return colors; } From 7b19cc64c6c35625d49b56c5272d466a451a89d5 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sun, 24 Apr 2016 01:36:02 -0700 Subject: [PATCH 011/297] Support customizable terminal font family --- src/vs/workbench/parts/terminal/common/terminal.ts | 1 + .../workbench/parts/terminal/node/terminal.contribution.ts | 5 +++++ src/vs/workbench/parts/terminal/node/terminalPanel.ts | 3 ++- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/parts/terminal/common/terminal.ts b/src/vs/workbench/parts/terminal/common/terminal.ts index 5420f41aff8..66b820c11c2 100644 --- a/src/vs/workbench/parts/terminal/common/terminal.ts +++ b/src/vs/workbench/parts/terminal/common/terminal.ts @@ -24,6 +24,7 @@ export interface ITerminalConfiguration { unixLike: string, windows: string }, + fontFamily: string, ansiColors: { black: string, red: string, diff --git a/src/vs/workbench/parts/terminal/node/terminal.contribution.ts b/src/vs/workbench/parts/terminal/node/terminal.contribution.ts index d56192488fb..2a94b34383d 100644 --- a/src/vs/workbench/parts/terminal/node/terminal.contribution.ts +++ b/src/vs/workbench/parts/terminal/node/terminal.contribution.ts @@ -33,6 +33,11 @@ configurationRegistry.registerConfiguration({ 'type': 'string', 'default': TERMINAL_DEFAULT_SHELL_WINDOWS }, + 'integratedTerminal.fontFamily': { + 'description': nls.localize('integratedTerminal.fontFamily', "The font family used by the terminal (CSS font-family format)."), + 'type': 'string', + 'default': 'Menlo, Monaco, Consolas, "Droid Sans Mono", "Courier New", monospace, "Droid Sans Fallback"' + }, 'integratedTerminal.ansiColors.black': { 'description': nls.localize('integratedTerminal.ansiColors.black', "Black color for terminals that support ANSI escape sequences (format: #rrggbb)"), 'type': 'string', diff --git a/src/vs/workbench/parts/terminal/node/terminalPanel.ts b/src/vs/workbench/parts/terminal/node/terminalPanel.ts index f9f3400173e..785c0ed073e 100644 --- a/src/vs/workbench/parts/terminal/node/terminalPanel.ts +++ b/src/vs/workbench/parts/terminal/node/terminalPanel.ts @@ -67,7 +67,8 @@ export class TerminalPanel extends Panel { this.terminal.open(this.terminalDomElement); this.parentDomElement.appendChild(terminalContainer.getDomNode()); - this.terminalDomElement.style.fontFamily = 'Hack, mono'; + let config = this.configurationService.getConfiguration(); + this.terminalDomElement.style.fontFamily = config.integratedTerminal.fontFamily; this.terminal.colors = this.getTerminalColors(); return TPromise.as(null); From a443f81f0fca3bfbb1fe59723bdabd8ac707a6e2 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sun, 24 Apr 2016 01:52:34 -0700 Subject: [PATCH 012/297] Use jeremyramin/term.js --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 16e4ad78843..395a21c5235 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "pty.js": "0.3.0", "sax": "1.1.2", "semver": "4.3.6", - "term.js": "0.0.7", + "term.js": "git+https://github.com/jeremyramin/term.js.git", "vscode-debugprotocol": "1.8.0-pre.3", "vscode-textmate": "1.0.11", "winreg": "1.2.0", From 11d3e047999784bba3a54dec8de14d16e4a7aa42 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sun, 24 Apr 2016 01:53:22 -0700 Subject: [PATCH 013/297] Focus terminal input if anywhere in panel is clicked --- .../parts/terminal/node/terminalPanel.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/vs/workbench/parts/terminal/node/terminalPanel.ts b/src/vs/workbench/parts/terminal/node/terminalPanel.ts index 785c0ed073e..77e494a9732 100644 --- a/src/vs/workbench/parts/terminal/node/terminalPanel.ts +++ b/src/vs/workbench/parts/terminal/node/terminalPanel.ts @@ -63,6 +63,11 @@ export class TerminalPanel extends Panel { this.ptyProcess.write(data); return false; }); + this.parentDomElement.addEventListener('mouseup', (event) => { + if (event.which !== 3) { + this.focusTerminal(); + } + }); this.terminal.open(this.terminalDomElement); this.parentDomElement.appendChild(terminalContainer.getDomNode()); @@ -74,6 +79,16 @@ export class TerminalPanel extends Panel { return TPromise.as(null); } + private focusTerminal(): void { + let text = window.getSelection().toString(); + if (!text) { + this.terminal.focus(); + if (this.terminal._textarea) { + this.terminal._textarea.focus(); + } + } + } + private getShell(): string { let config = this.configurationService.getConfiguration(); if (platform.isWindows) { From fca7837bc1cb2aa55f329bccf25f640ed57e8df1 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sun, 24 Apr 2016 02:11:08 -0700 Subject: [PATCH 014/297] Fix terminal light theme colors The foreground color was not set so the editor's color was used --- .../node/media/terminal.contribution.css | 23 ++++++++----------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/src/vs/workbench/parts/terminal/node/media/terminal.contribution.css b/src/vs/workbench/parts/terminal/node/media/terminal.contribution.css index 10486b5a9bb..66734e11371 100644 --- a/src/vs/workbench/parts/terminal/node/media/terminal.contribution.css +++ b/src/vs/workbench/parts/terminal/node/media/terminal.contribution.css @@ -8,28 +8,25 @@ display: flex; } -.monaco-workbench .integrated-terminal .terminal span { - display: inline-block; /* make terminal characters cover height of line */ +.monaco-workbench .integrated-terminal { + background-color: #1e1e1e!important; + color: #CCC; } .monaco-workbench .integrated-terminal .terminal { background-color: #1e1e1e!important; } -.monaco-workbench .terminal-cursor { - background-color: #1e1e1e; +.monaco-workbench .integrated-terminal .terminal span { + display: inline-block; /* make terminal characters cover height of line */ } -.monaco-workbench .reverse-video { - color: #CCC; -} - -.vs-dark .monaco-workbench .terminal-cursor { +.monaco-workbench .integrated-terminal .terminal-cursor { background-color: #CCC; } -.vs-dark .monaco-workbench .reverse-video { - color: #252526; +.monaco-workbench .integrated-terminal .reverse-video { + color: #1e1e1e; } /* High Contrast Theming */ @@ -38,10 +35,10 @@ background-color: black!important; } -.hc-dark .monaco-workbench .terminal-cursor { +.hc-dark .monaco-workbench .integrated-terminal .terminal-cursor { background-color: white; } -.hc-dark .monaco-workbench .reverse-video { +.hc-dark .monaco-workbench .integrated-terminal .reverse-video { color: black; } \ No newline at end of file From 08fcd6b5a0141071c094ff16d6f2347a18a5c159 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sun, 24 Apr 2016 03:06:32 -0700 Subject: [PATCH 015/297] Fix terminal selection --- .../parts/terminal/node/media/terminal.contribution.css | 1 + src/vs/workbench/parts/terminal/node/term.js.d.ts | 2 +- src/vs/workbench/parts/terminal/node/terminalPanel.ts | 4 +++- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/parts/terminal/node/media/terminal.contribution.css b/src/vs/workbench/parts/terminal/node/media/terminal.contribution.css index 66734e11371..1a31ddb8288 100644 --- a/src/vs/workbench/parts/terminal/node/media/terminal.contribution.css +++ b/src/vs/workbench/parts/terminal/node/media/terminal.contribution.css @@ -11,6 +11,7 @@ .monaco-workbench .integrated-terminal { background-color: #1e1e1e!important; color: #CCC; + -webkit-user-select: initial; } .monaco-workbench .integrated-terminal .terminal { diff --git a/src/vs/workbench/parts/terminal/node/term.js.d.ts b/src/vs/workbench/parts/terminal/node/term.js.d.ts index 9f2c4c7ea9e..faa6d112d7a 100644 --- a/src/vs/workbench/parts/terminal/node/term.js.d.ts +++ b/src/vs/workbench/parts/terminal/node/term.js.d.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ declare module 'term.js' { - function init(): TermJsTerminal; + function init(options: any): TermJsTerminal; // There seems to be no way to export this so it can be referenced outside of this file when a // module is a function. diff --git a/src/vs/workbench/parts/terminal/node/terminalPanel.ts b/src/vs/workbench/parts/terminal/node/terminalPanel.ts index 77e494a9732..2ca313b5547 100644 --- a/src/vs/workbench/parts/terminal/node/terminalPanel.ts +++ b/src/vs/workbench/parts/terminal/node/terminalPanel.ts @@ -54,7 +54,9 @@ export class TerminalPanel extends Panel { this.parentDomElement.classList.add('integrated-terminal'); let terminalScrollable = new DomNodeScrollable(this.terminalDomElement); let terminalContainer = new ScrollableElement(this.terminalDomElement, terminalScrollable, { horizontal: 'hidden', vertical: 'auto' }); - this.terminal = termJs(); + this.terminal = termJs({ + cursorBlink: false + }); this.ptyProcess.on('data', (data) => { this.terminal.write(data); From d1d8c0f1ac70bb587bd786b6e1d2924ea7217f41 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sun, 24 Apr 2016 03:06:50 -0700 Subject: [PATCH 016/297] Use jeremyramin/pty.js --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 395a21c5235..16460c1fe36 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "https-proxy-agent": "0.3.6", "iconv-lite": "0.4.13", "native-keymap": "0.1.2", - "pty.js": "0.3.0", + "pty.js": "git+https://github.com/jeremyramin/pty.js.git#28f2667", "sax": "1.1.2", "semver": "4.3.6", "term.js": "git+https://github.com/jeremyramin/term.js.git", From 5194caaf45534fab1956abab0d0e51c6802d0555 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sun, 24 Apr 2016 03:09:20 -0700 Subject: [PATCH 017/297] Fix middle click to paste on Linux when clicking on selection --- src/vs/workbench/parts/terminal/node/terminalPanel.ts | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/parts/terminal/node/terminalPanel.ts b/src/vs/workbench/parts/terminal/node/terminalPanel.ts index 2ca313b5547..468240d0c26 100644 --- a/src/vs/workbench/parts/terminal/node/terminalPanel.ts +++ b/src/vs/workbench/parts/terminal/node/terminalPanel.ts @@ -65,6 +65,13 @@ export class TerminalPanel extends Panel { this.ptyProcess.write(data); return false; }); + this.parentDomElement.addEventListener('mousedown', (event) => { + // Drop selection and focus terminal on Linux to enable middle button paste when click + // occurs on the selection itself. + if (event.which === 2 && platform.isLinux) { + this.focusTerminal(true); + } + }); this.parentDomElement.addEventListener('mouseup', (event) => { if (event.which !== 3) { this.focusTerminal(); @@ -81,9 +88,9 @@ export class TerminalPanel extends Panel { return TPromise.as(null); } - private focusTerminal(): void { + private focusTerminal(force?: boolean): void { let text = window.getSelection().toString(); - if (!text) { + if (!text || force) { this.terminal.focus(); if (this.terminal._textarea) { this.terminal._textarea.focus(); From 45753f95bfbe591c2878755f45357c2cfb91c738 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sun, 24 Apr 2016 03:10:42 -0700 Subject: [PATCH 018/297] Add clarifying comment --- src/vs/workbench/parts/terminal/node/terminalPanel.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/parts/terminal/node/terminalPanel.ts b/src/vs/workbench/parts/terminal/node/terminalPanel.ts index 468240d0c26..22371c584a6 100644 --- a/src/vs/workbench/parts/terminal/node/terminalPanel.ts +++ b/src/vs/workbench/parts/terminal/node/terminalPanel.ts @@ -55,7 +55,7 @@ export class TerminalPanel extends Panel { let terminalScrollable = new DomNodeScrollable(this.terminalDomElement); let terminalContainer = new ScrollableElement(this.terminalDomElement, terminalScrollable, { horizontal: 'hidden', vertical: 'auto' }); this.terminal = termJs({ - cursorBlink: false + cursorBlink: false // term.js' blinking cursor breaks selection }); this.ptyProcess.on('data', (data) => { From 49220160ee3f25df1bcf0a828f21718501ce30da Mon Sep 17 00:00:00 2001 From: Inori Date: Sun, 24 Apr 2016 18:16:07 +0800 Subject: [PATCH 019/297] add selectAllMatches command --- .../contrib/find/common/findController.ts | 12 +++++ .../editor/contrib/find/common/findModel.ts | 18 ++++++- .../find/common/selectAllMatchesCommand.ts | 48 +++++++++++++++++++ 3 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 src/vs/editor/contrib/find/common/selectAllMatchesCommand.ts diff --git a/src/vs/editor/contrib/find/common/findController.ts b/src/vs/editor/contrib/find/common/findController.ts index f760bacdf6a..795ab04aacc 100644 --- a/src/vs/editor/contrib/find/common/findController.ts +++ b/src/vs/editor/contrib/find/common/findController.ts @@ -220,6 +220,15 @@ export class CommonFindController extends Disposable implements editorCommon.IEd } return false; } + + public selectAllMatches(): boolean { + if (this._model) { + this._model.selectAll(); + this.closeFindWidget(); + return true; + } + return false; + } } export class StartFindAction extends EditorAction { @@ -722,3 +731,6 @@ registerFindCommand(FIND_IDS.ReplaceOneAction, x => x.replace(), { registerFindCommand(FIND_IDS.ReplaceAllAction, x => x.replaceAll(), { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.Enter }); +registerFindCommand(FIND_IDS.SelectAllMatchesAction, x => x.selectAllMatches(), { + primary: KeyMod.Alt | KeyCode.Enter +}); diff --git a/src/vs/editor/contrib/find/common/findModel.ts b/src/vs/editor/contrib/find/common/findModel.ts index 9b236576ef0..cbaa28b471c 100644 --- a/src/vs/editor/contrib/find/common/findModel.ts +++ b/src/vs/editor/contrib/find/common/findModel.ts @@ -14,6 +14,7 @@ import * as editorCommon from 'vs/editor/common/editorCommon'; import {FindDecorations} from './findDecorations'; import {FindReplaceState, FindReplaceStateChangedEvent} from './findState'; import {ReplaceAllCommand} from './replaceAllCommand'; +import {SelectAllMatchesCommand} from './selectAllMatchesCommand'; export const FIND_IDS = { StartFindAction: 'actions.find', @@ -29,7 +30,8 @@ export const FIND_IDS = { ToggleWholeWordCommand: 'toggleFindWholeWord', ToggleRegexCommand: 'toggleFindRegex', ReplaceOneAction: 'editor.action.replaceOne', - ReplaceAllAction: 'editor.action.replaceAll' + ReplaceAllAction: 'editor.action.replaceAll', + SelectAllMatchesAction: 'editor.action.selectAllMatches' }; export const MATCHES_LIMIT = 999; @@ -350,6 +352,20 @@ export class FindModelBoundToEditorModel { this.research(false); } + public selectAll(): void { + if (!this._hasMatches()) { + return; + } + + let findScope = this._decorations.getFindScope(); + + // Get all the ranges (even more than the highlighted ones) + let ranges = this._findMatches(findScope, Number.MAX_VALUE); + + let command = new SelectAllMatchesCommand(this._editor, ranges); + this._executeEditorCommand('selectAllMatches', command); + } + private _executeEditorCommand(source:string, command:editorCommon.ICommand): void { try { this._ignoreModelContentChanged = true; diff --git a/src/vs/editor/contrib/find/common/selectAllMatchesCommand.ts b/src/vs/editor/contrib/find/common/selectAllMatchesCommand.ts new file mode 100644 index 00000000000..97bb671caff --- /dev/null +++ b/src/vs/editor/contrib/find/common/selectAllMatchesCommand.ts @@ -0,0 +1,48 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +import {Selection} from 'vs/editor/common/core/selection'; +import {ISelection} from 'vs/editor/common/editorCommon'; +import * as editorCommon from 'vs/editor/common/editorCommon'; + +export class SelectAllMatchesCommand implements editorCommon.ICommand { + + private _editor:editorCommon.ICommonCodeEditor; + private _ranges: editorCommon.IEditorRange[]; + + constructor(editor:editorCommon.ICommonCodeEditor, ranges: editorCommon.IEditorRange[]) { + this._editor = editor; + this._ranges = ranges; + } + + public getEditOperations(model:editorCommon.ITokenizedModel, builder:editorCommon.IEditOperationBuilder): void { + if (this._ranges.length > 0) { + // Collect all select operations + let newSelections = new Array(); + for (var i = 0; i < this._ranges.length; i++) { + newSelections.push({ + selectionStartLineNumber: this._ranges[i].startLineNumber, + selectionStartColumn: this._ranges[i].startColumn, + positionLineNumber: this._ranges[i].startLineNumber, + positionColumn: this._ranges[i].endColumn + }); + } + + this._editor.setSelections(newSelections); + } + } + + public computeCursorState(model:editorCommon.ITokenizedModel, helper: editorCommon.ICursorStateComputerData): editorCommon.IEditorSelection { + var inverseEditOperations = helper.getInverseEditOperations(); + var srcRange = inverseEditOperations[inverseEditOperations.length - 1].range; + return Selection.createSelection( + srcRange.endLineNumber, + srcRange.endColumn, + srcRange.endLineNumber, + srcRange.endColumn + ); + } +} \ No newline at end of file From 4e289c3f4d24c96712b05433099ed979b1589937 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sun, 24 Apr 2016 03:38:14 -0700 Subject: [PATCH 020/297] Add process title to pty.js interface --- src/vs/workbench/parts/terminal/node/pty.js.d.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/vs/workbench/parts/terminal/node/pty.js.d.ts b/src/vs/workbench/parts/terminal/node/pty.js.d.ts index 0c44c428c51..25b7054d4d0 100644 --- a/src/vs/workbench/parts/terminal/node/pty.js.d.ts +++ b/src/vs/workbench/parts/terminal/node/pty.js.d.ts @@ -9,6 +9,10 @@ declare module 'pty.js' { export function createTerminal(file: string, args: string[], options: any): Terminal; export interface Terminal { + /** + * The title of the active process. + */ + process: string; on(event: string, callback: (data: any) => void): void; resize(columns: number, rows: number): void; write(data: string): void; From 1fdc39a29a7c0d93a23cce0f780447a39cbfcb9b Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sun, 24 Apr 2016 03:44:58 -0700 Subject: [PATCH 021/297] Open terminal in the workspace root if available --- src/vs/workbench/parts/terminal/node/terminalPanel.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/parts/terminal/node/terminalPanel.ts b/src/vs/workbench/parts/terminal/node/terminalPanel.ts index 22371c584a6..41d1843123a 100644 --- a/src/vs/workbench/parts/terminal/node/terminalPanel.ts +++ b/src/vs/workbench/parts/terminal/node/terminalPanel.ts @@ -11,6 +11,7 @@ import {TPromise} from 'vs/base/common/winjs.base'; import {Builder, Dimension} from 'vs/base/browser/builder'; import {IConfigurationService} from 'vs/platform/configuration/common/configuration'; import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry'; +import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace'; import {ITerminalConfiguration, TERMINAL_PANEL_ID} from 'vs/workbench/parts/terminal/common/terminal'; import {Panel} from 'vs/workbench/browser/panel'; import {ScrollableElement} from 'vs/base/browser/ui/scrollbar/scrollableElementImpl'; @@ -28,7 +29,8 @@ export class TerminalPanel extends Panel { constructor( @IConfigurationService private configurationService: IConfigurationService, - @ITelemetryService telemetryService: ITelemetryService + @ITelemetryService telemetryService: ITelemetryService, + @IWorkspaceContextService private contextService: IWorkspaceContextService ) { super(TERMINAL_PANEL_ID, telemetryService); } @@ -47,7 +49,7 @@ export class TerminalPanel extends Panel { name: fs.existsSync('/usr/share/terminfo/x/xterm-256color') ? 'xterm-256color' : 'xterm', cols: 80, rows: 6, - cwd: process.env.HOME + cwd: this.contextService.getWorkspace() ? this.contextService.getWorkspace().resource.path : process.env.HOME }); this.parentDomElement = parent.getHTMLElement(); this.terminalDomElement = document.createElement('div'); From deaa5f90089c5a94100042a6eab23d346bd3eb9c Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sun, 24 Apr 2016 03:58:55 -0700 Subject: [PATCH 022/297] Handle exit by opening a new terminal This is temporary until multiple terminals are available. --- .../workbench/parts/terminal/node/pty.js.d.ts | 3 +++ .../parts/terminal/node/terminalPanel.ts | 18 +++++++++++++++--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/parts/terminal/node/pty.js.d.ts b/src/vs/workbench/parts/terminal/node/pty.js.d.ts index 25b7054d4d0..cc726238aa2 100644 --- a/src/vs/workbench/parts/terminal/node/pty.js.d.ts +++ b/src/vs/workbench/parts/terminal/node/pty.js.d.ts @@ -13,8 +13,11 @@ declare module 'pty.js' { * The title of the active process. */ process: string; + on(event: string, callback: (data: any) => void): void; + resize(columns: number, rows: number): void; + write(data: string): void; } } \ No newline at end of file diff --git a/src/vs/workbench/parts/terminal/node/terminalPanel.ts b/src/vs/workbench/parts/terminal/node/terminalPanel.ts index 41d1843123a..f9d134a5fd8 100644 --- a/src/vs/workbench/parts/terminal/node/terminalPanel.ts +++ b/src/vs/workbench/parts/terminal/node/terminalPanel.ts @@ -45,13 +45,20 @@ export class TerminalPanel extends Panel { public create(parent: Builder): TPromise { super.create(parent); + this.parentDomElement = parent.getHTMLElement(); + this.createTerminal(); + + return TPromise.as(null); + } + + private createTerminal(): void { + this.parentDomElement.innerHTML = ''; this.ptyProcess = fork(this.getShell(), [], { name: fs.existsSync('/usr/share/terminfo/x/xterm-256color') ? 'xterm-256color' : 'xterm', cols: 80, rows: 6, cwd: this.contextService.getWorkspace() ? this.contextService.getWorkspace().resource.path : process.env.HOME }); - this.parentDomElement = parent.getHTMLElement(); this.terminalDomElement = document.createElement('div'); this.parentDomElement.classList.add('integrated-terminal'); let terminalScrollable = new DomNodeScrollable(this.terminalDomElement); @@ -67,6 +74,13 @@ export class TerminalPanel extends Panel { this.ptyProcess.write(data); return false; }); + this.ptyProcess.on('exit', (data) => { + this.terminal.destroy(); + // TODO: When multiple terminals are supported this should do something smarter. There is + // also a weird bug here at leasy on Ubuntu 15.10 where the new terminal text does not + // repaint correctly. + this.createTerminal(); + }); this.parentDomElement.addEventListener('mousedown', (event) => { // Drop selection and focus terminal on Linux to enable middle button paste when click // occurs on the selection itself. @@ -86,8 +100,6 @@ export class TerminalPanel extends Panel { let config = this.configurationService.getConfiguration(); this.terminalDomElement.style.fontFamily = config.integratedTerminal.fontFamily; this.terminal.colors = this.getTerminalColors(); - - return TPromise.as(null); } private focusTerminal(force?: boolean): void { From a4c9ed7203b275b400812892e5c8a7d60a0ec2ea Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sun, 24 Apr 2016 04:17:33 -0700 Subject: [PATCH 023/297] Fix bug where terminal output could obscure panel title --- .../parts/terminal/node/media/terminal.contribution.css | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vs/workbench/parts/terminal/node/media/terminal.contribution.css b/src/vs/workbench/parts/terminal/node/media/terminal.contribution.css index 1a31ddb8288..ff499f7f13d 100644 --- a/src/vs/workbench/parts/terminal/node/media/terminal.contribution.css +++ b/src/vs/workbench/parts/terminal/node/media/terminal.contribution.css @@ -12,6 +12,7 @@ background-color: #1e1e1e!important; color: #CCC; -webkit-user-select: initial; + overflow: hidden; /* prevents the terminal output being incorrectly placed over the title */ } .monaco-workbench .integrated-terminal .terminal { From aeb155d32e6a4f246c3ebeb149b577041af39d4d Mon Sep 17 00:00:00 2001 From: Inori Date: Mon, 25 Apr 2016 09:23:16 +0800 Subject: [PATCH 024/297] rename 'selectAll' to 'selectAllMatches' --- src/vs/editor/contrib/find/common/findController.ts | 2 +- src/vs/editor/contrib/find/common/findModel.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/editor/contrib/find/common/findController.ts b/src/vs/editor/contrib/find/common/findController.ts index 795ab04aacc..8578cbecc0b 100644 --- a/src/vs/editor/contrib/find/common/findController.ts +++ b/src/vs/editor/contrib/find/common/findController.ts @@ -223,7 +223,7 @@ export class CommonFindController extends Disposable implements editorCommon.IEd public selectAllMatches(): boolean { if (this._model) { - this._model.selectAll(); + this._model.selectAllMatches(); this.closeFindWidget(); return true; } diff --git a/src/vs/editor/contrib/find/common/findModel.ts b/src/vs/editor/contrib/find/common/findModel.ts index cbaa28b471c..1c14ecbef76 100644 --- a/src/vs/editor/contrib/find/common/findModel.ts +++ b/src/vs/editor/contrib/find/common/findModel.ts @@ -352,7 +352,7 @@ export class FindModelBoundToEditorModel { this.research(false); } - public selectAll(): void { + public selectAllMatches(): void { if (!this._hasMatches()) { return; } From c84977cec61c979a8398156e8abdd0a961a72abe Mon Sep 17 00:00:00 2001 From: aioute Gao Date: Mon, 25 Apr 2016 12:41:57 +0900 Subject: [PATCH 025/297] Add tests for validatePosition. --- .../test/common/model/textModel.test.ts | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/vs/editor/test/common/model/textModel.test.ts b/src/vs/editor/test/common/model/textModel.test.ts index 67d7f40eb08..0b2c973cee4 100644 --- a/src/vs/editor/test/common/model/textModel.test.ts +++ b/src/vs/editor/test/common/model/textModel.test.ts @@ -434,12 +434,36 @@ suite('Editor Model - TextModel', () => { ], 'mixed whitespace 2'); }); + test('validatePosition', () => { + + var m = new TextModel([], TextModel.toRawText('line one\nline two', TextModel.DEFAULT_CREATION_OPTIONS)); + + assert.deepEqual(m.validatePosition(new Position(0, 0)), new Position(1, 1)); + assert.deepEqual(m.validatePosition(new Position(0, 1)), new Position(1, 1)); + + assert.deepEqual(m.validatePosition(new Position(1, 1)), new Position(1, 1)); + assert.deepEqual(m.validatePosition(new Position(1, 2)), new Position(1, 2)); + assert.deepEqual(m.validatePosition(new Position(1, 30)), new Position(1, 9)); + + assert.deepEqual(m.validatePosition(new Position(2, 0)), new Position(2, 1)); + assert.deepEqual(m.validatePosition(new Position(2, 1)), new Position(2, 1)); + assert.deepEqual(m.validatePosition(new Position(2, 2)), new Position(2, 2)); + assert.deepEqual(m.validatePosition(new Position(2, 30)), new Position(2, 9)); + + assert.deepEqual(m.validatePosition(new Position(3, 0)), new Position(2, 9)); + assert.deepEqual(m.validatePosition(new Position(3, 1)), new Position(2, 9)); + assert.deepEqual(m.validatePosition(new Position(3, 30)), new Position(2, 9)); + + assert.deepEqual(m.validatePosition(new Position(30, 30)), new Position(2, 9)); + + }); + test('modifyPosition', () => { var m = new TextModel([], TextModel.toRawText('line one\nline two', TextModel.DEFAULT_CREATION_OPTIONS)); assert.deepEqual(m.modifyPosition(new Position(1,1), 0), new Position(1, 1)); assert.deepEqual(m.modifyPosition(new Position(0,0), 0), new Position(1, 1)); - assert.deepEqual(m.modifyPosition(new Position(30, 1), 0), new Position(2, 1)); + assert.deepEqual(m.modifyPosition(new Position(30, 1), 0), new Position(2, 9)); assert.deepEqual(m.modifyPosition(new Position(1,1), 17), new Position(2, 9)); assert.deepEqual(m.modifyPosition(new Position(1,1), 1), new Position(1, 2)); From 37c80ba8c38f36edf1ebc74150c0abb394e9909d Mon Sep 17 00:00:00 2001 From: Yuki Ueda Date: Tue, 26 Apr 2016 12:34:09 +0900 Subject: [PATCH 026/297] fixed #5412 --- .../accessibility/browser/accessibility.ts | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/src/vs/editor/contrib/accessibility/browser/accessibility.ts b/src/vs/editor/contrib/accessibility/browser/accessibility.ts index 6bc1edd0fe3..4c76129a72d 100644 --- a/src/vs/editor/contrib/accessibility/browser/accessibility.ts +++ b/src/vs/editor/contrib/accessibility/browser/accessibility.ts @@ -161,22 +161,6 @@ class AccessibilityHelpWidget extends Widget implements IOverlayWidget { text += '\n\n - ' + this._descriptionForCommand(ToggleTabFocusModeAction.ID, NLS_TAB_FOCUS_MODE_OFF, NLS_TAB_FOCUS_MODE_OFF_NO_KB); } - const NLS_EXPERIMENTAL_SCREENREADER_OPTS_ON = nls.localize('experimentalScreenReaderOptsOn', "Experimental screen reader support is turned on due to editor.experimentalScreenReader settings key."); - const NLS_EXPERIMENTAL_SCREENREADER_SESSION_ON = nls.localize('experimentalScreenReaderSessionOn', "Experimental screen reader support is turned on for this session. Toggle this behaviour by pressing {0}."); - const NLS_EXPERIMENTAL_SCREENREADER_SESSION_ON_NO_KB = nls.localize('experimentalScreenReaderSessionOnNoKb', "Experimental screen reader support is turned on for this session. The command {0} is currently not triggerable by a keybinding."); - const NLS_EXPERIMENTAL_SCREENREADER_SESSION_OFF = nls.localize('experimentalScreenReaderSessionOff', "Experimental screen reader support is turned off. Turn it on for this session by pressing {0} or turn it on for all sessions by configuring the editor.experimentalScreenReader setting to true."); - const NLS_EXPERIMENTAL_SCREENREADER_SESSION_OFF_NO_KB = nls.localize('experimentalScreenReaderSessionOffNoKb', "Experimental screen reader support is turned off. The command {0} is currently not triggerable by a keybinding. Turn it on for all sessions by configuring the editor.experimentalScreenReader setting to true."); - - if (opts.experimentalScreenReader) { - text += '\n\n - ' + NLS_EXPERIMENTAL_SCREENREADER_OPTS_ON; - } else { - if (GlobalScreenReaderNVDA.getValue()) { - text += '\n\n - ' + this._descriptionForCommand(TOGGLE_EXPERIMENTAL_SCREEN_READER_SUPPORT_COMMAND_ID, NLS_EXPERIMENTAL_SCREENREADER_SESSION_ON, NLS_EXPERIMENTAL_SCREENREADER_SESSION_ON_NO_KB); - } else { - text += '\n\n - ' + this._descriptionForCommand(TOGGLE_EXPERIMENTAL_SCREEN_READER_SUPPORT_COMMAND_ID, NLS_EXPERIMENTAL_SCREENREADER_SESSION_OFF, NLS_EXPERIMENTAL_SCREENREADER_SESSION_OFF_NO_KB); - } - } - text += '\n\n' + nls.localize('outroMsg', "You can dismiss this tooltip and return to the editor by pressing Escape."); this._domNode.appendChild(renderHtml({ From 704d021af7f72fe10f63eb0f1a759aef0b4813c8 Mon Sep 17 00:00:00 2001 From: Yuki Ueda Date: Tue, 26 Apr 2016 14:08:33 +0900 Subject: [PATCH 027/297] Delete locate --- .../contrib/accessibility/browser/accessibility.i18n.json | 5 ----- .../contrib/accessibility/browser/accessibility.i18n.json | 5 ----- .../contrib/accessibility/browser/accessibility.i18n.json | 5 ----- .../contrib/accessibility/browser/accessibility.i18n.json | 5 ----- .../contrib/accessibility/browser/accessibility.i18n.json | 5 ----- .../contrib/accessibility/browser/accessibility.i18n.json | 5 ----- .../contrib/accessibility/browser/accessibility.i18n.json | 5 ----- .../contrib/accessibility/browser/accessibility.i18n.json | 5 ----- 8 files changed, 40 deletions(-) diff --git a/i18n/chs/src/vs/editor/contrib/accessibility/browser/accessibility.i18n.json b/i18n/chs/src/vs/editor/contrib/accessibility/browser/accessibility.i18n.json index 3e8f1ca9b9e..46d5b868f43 100644 --- a/i18n/chs/src/vs/editor/contrib/accessibility/browser/accessibility.i18n.json +++ b/i18n/chs/src/vs/editor/contrib/accessibility/browser/accessibility.i18n.json @@ -5,11 +5,6 @@ // Do not edit this file. It is machine generated. { "ShowAccessibilityHelpAction": "显示辅助功能帮助", - "experimentalScreenReaderOptsOn": "实验屏幕阅读器支持因 editor.experimentalScreenReader 设置键而开启。", - "experimentalScreenReaderSessionOff": "实验屏幕阅读器支持已关闭。通过按 {0} 为此对话开启它或通过将 editor.experimentalScreenReader 设置配置为 true 为所有对话开启它。", - "experimentalScreenReaderSessionOffNoKb": "实验屏幕阅读器支持已关闭。当前无法通过键绑定触发命令 {0}。通过将 editor.experimentalScreenReader 设置配置为 true 为所有对话开启它。", - "experimentalScreenReaderSessionOn": "为此对话开启实验屏幕阅读器支持。通过按 {0} 切换此行为。", - "experimentalScreenReaderSessionOnNoKb": "为此对话开启了实验屏幕阅读器支持。当前无法通过键绑定触发命令 {0}。", "introMsg": "感谢试用 VS 代码的实验辅助功能选项。", "outroMsg": "可以通过按 Esc 消除此工具提示并返回到编辑器。", "status": "状态:", diff --git a/i18n/cht/src/vs/editor/contrib/accessibility/browser/accessibility.i18n.json b/i18n/cht/src/vs/editor/contrib/accessibility/browser/accessibility.i18n.json index 35be0ed912d..7086aa8650b 100644 --- a/i18n/cht/src/vs/editor/contrib/accessibility/browser/accessibility.i18n.json +++ b/i18n/cht/src/vs/editor/contrib/accessibility/browser/accessibility.i18n.json @@ -5,11 +5,6 @@ // Do not edit this file. It is machine generated. { "ShowAccessibilityHelpAction": "顯示協助工具說明", - "experimentalScreenReaderOptsOn": "因為 editor.experimentalScreenReader 設定索引鍵的緣故,所以已開啟實驗螢幕助讀程式支援。", - "experimentalScreenReaderSessionOff": "實驗螢幕助讀程式支援已關閉。請按 {0} 以針對此工作階段加以開啟,或將 editor.experimentalScreenReader 設定為 True 以針對所有工作階段加以開啟。", - "experimentalScreenReaderSessionOffNoKb": "實驗螢幕助讀程式支援已關閉。目前無法透過按鍵繫結關係觸發命令 {0}。請將 editor.experimentalScreenReader 設定為 True,以針對所有工作階段加以開啟。", - "experimentalScreenReaderSessionOn": "此工作階段的實驗螢幕助讀程式支援已開啟。按 {0} 可切換此行為。", - "experimentalScreenReaderSessionOnNoKb": "此工作階段的實驗螢幕助讀程式支援已開啟。目前無法透過按鍵繫結關係觸發命令 {0}。", "introMsg": "感謝您試用 VSCode 的實驗協助工具選項。", "outroMsg": "您可以按 Esc 鍵來解除此工具提示並返回編輯器。", "status": "狀態:", diff --git a/i18n/deu/src/vs/editor/contrib/accessibility/browser/accessibility.i18n.json b/i18n/deu/src/vs/editor/contrib/accessibility/browser/accessibility.i18n.json index 9bd85823e40..e7e5d37b71f 100644 --- a/i18n/deu/src/vs/editor/contrib/accessibility/browser/accessibility.i18n.json +++ b/i18n/deu/src/vs/editor/contrib/accessibility/browser/accessibility.i18n.json @@ -5,11 +5,6 @@ // Do not edit this file. It is machine generated. { "ShowAccessibilityHelpAction": "Hilfe zur Barrierefreiheit anzeigen", - "experimentalScreenReaderOptsOn": "Experimentelle Sprachausgabeunterstützung ist aufgrund des Einstellungsschlüssels \"editor.experimentalScreenReader\" aktiviert.", - "experimentalScreenReaderSessionOff": "Experimentelle Sprachausgabeunterstützung ist deaktiviert. Aktivieren sie diese Option für diese Sitzung, indem Sie {0} drücken, oder aktivieren Sie sie für alle Sitzungen, indem Sie die Einstellung \"editor.experimentalScreenReader\" auf \"true\" festlegen.", - "experimentalScreenReaderSessionOffNoKb": "Experimentelle Sprachausgabeunterstützung ist deaktiviert. Der Befehl kann {0} zurzeit nicht durch eine Tastenbindung ausgelöst werden. Aktivieren Sie diese Option für alle Sitzungen, indem Sie die Einstellung \"editor.experimentalScreenReader\" auf \"true\" festlegen.", - "experimentalScreenReaderSessionOn": "Experimentelle Sprachausgabeunterstützung ist für diese Sitzung aktiviert. Schalten Sie dieses Verhalten durch Drücken von {0} um.", - "experimentalScreenReaderSessionOnNoKb": "Experimentelle Sprachausgabeunterstützung ist für diese Sitzung aktiviert. Der Befehl kann {0} zurzeit nicht durch eine Tastenbindung ausgelöst werden.", "introMsg": "Vielen Dank, dass Sie die experimentellen Optionen für Barrierefreiheit von VS Code testen.", "outroMsg": "Sie können diese QuickInfo schließen und durch Drücken von ESC zum Editor zurückkehren.", "status": "Status:", diff --git a/i18n/esn/src/vs/editor/contrib/accessibility/browser/accessibility.i18n.json b/i18n/esn/src/vs/editor/contrib/accessibility/browser/accessibility.i18n.json index 839dc76eaed..a3dad1faf6c 100644 --- a/i18n/esn/src/vs/editor/contrib/accessibility/browser/accessibility.i18n.json +++ b/i18n/esn/src/vs/editor/contrib/accessibility/browser/accessibility.i18n.json @@ -5,11 +5,6 @@ // Do not edit this file. It is machine generated. { "ShowAccessibilityHelpAction": "Mostrar ayuda de accesibilidad", - "experimentalScreenReaderOptsOn": "La compatibilidad con el lector de pantalla experimental está desactivada debido a la clave de configuración editor.experimentalScreenReader.", - "experimentalScreenReaderSessionOff": "La compatibilidad con el lector de pantalla experimental está desactivada. Presione {0} para activarla en esta sesión o configure el valor editor.experimentalScreenReader como true para activarla en todas las sesiones.", - "experimentalScreenReaderSessionOffNoKb": "La compatibilidad con el lector de pantalla experimental está desactivada. El comando {0} no se puede desencadenar actualmente mediante un enlace de teclado. Configure el valor editor.experimentalScreenReader como true para activarla en todas las sesiones.", - "experimentalScreenReaderSessionOn": "La compatibilidad con el lector de pantalla experimental está activada para esta sesión. Presione {0} para desactivar o activar este comportamiento.", - "experimentalScreenReaderSessionOnNoKb": "La compatibilidad con el lector de pantalla experimental está activada para esta sesión. El comando {0} no se puede desencadenar actualmente mediante un enlace de teclado.", "introMsg": "Gracias por probar las opciones de accesibilidad experimentales de VS Code.", "outroMsg": "Para descartar esta información sobre herramientas y volver al editor, presione Esc.", "status": "Estado:", diff --git a/i18n/fra/src/vs/editor/contrib/accessibility/browser/accessibility.i18n.json b/i18n/fra/src/vs/editor/contrib/accessibility/browser/accessibility.i18n.json index 7530922c2e9..ad8c8f4d6b2 100644 --- a/i18n/fra/src/vs/editor/contrib/accessibility/browser/accessibility.i18n.json +++ b/i18n/fra/src/vs/editor/contrib/accessibility/browser/accessibility.i18n.json @@ -5,11 +5,6 @@ // Do not edit this file. It is machine generated. { "ShowAccessibilityHelpAction": "Afficher l'aide sur l'accessibilité", - "experimentalScreenReaderOptsOn": "La prise en charge du lecteur d'écran expérimental est activée en raison de la clé de paramètres editor.experimentalScreenReader.", - "experimentalScreenReaderSessionOff": "La prise en charge du lecteur d'écran expérimental est désactivée. Activez-la pour cette session en appuyant sur {0}, ou activez-la pour toutes les sessions en affectant au paramètre editor.experimentalScreenReader la valeur true.", - "experimentalScreenReaderSessionOffNoKb": "La prise en charge du lecteur d'écran expérimental est désactivée. Actuellement, la commande {0} ne peut pas être déclenchée par une combinaison de touches. Activez-la pour toutes les sessions en affectant au paramètre editor.experimentalScreenReader la valeur true.", - "experimentalScreenReaderSessionOn": "La prise en charge du lecteur d'écran expérimental est activée pour cette session. Activez ou désactivez ce comportement en appuyant sur {0}.", - "experimentalScreenReaderSessionOnNoKb": "La prise en charge du lecteur d'écran expérimental est activée pour cette session. Actuellement, la commande {0} ne peut pas être déclenchée par une combinaison de touches.", "introMsg": "Merci de tester les options d'accessibilité expérimentales de VS Code.", "outroMsg": "Vous pouvez masquer cette info-bulle et revenir à l'éditeur en appuyant sur Échap.", "status": "État :", diff --git a/i18n/ita/src/vs/editor/contrib/accessibility/browser/accessibility.i18n.json b/i18n/ita/src/vs/editor/contrib/accessibility/browser/accessibility.i18n.json index 382dd40eca1..7a74c512978 100644 --- a/i18n/ita/src/vs/editor/contrib/accessibility/browser/accessibility.i18n.json +++ b/i18n/ita/src/vs/editor/contrib/accessibility/browser/accessibility.i18n.json @@ -5,11 +5,6 @@ // Do not edit this file. It is machine generated. { "ShowAccessibilityHelpAction": "Visualizza la Guida sull'accessibilità", - "experimentalScreenReaderOptsOn": "Il supporto per l'utilità per la lettura dello schermo sperimentale è attivato perché è presente la chiave delle impostazioni editor.experimentalScreenReader.", - "experimentalScreenReaderSessionOff": "Il supporto per l'utilità per la lettura dello schermo sperimentale è disattivato. Per attivarlo per questa sessione, premere {0}; per attivarlo per tutte le sessioni, impostare editor.experimentalScreenReader su true.", - "experimentalScreenReaderSessionOffNoKb": "Il supporto per l'utilità per la lettura dello schermo sperimentale è disattivato. Il comando {0} non è attualmente attivabile con un tasto di scelta rapida. Per attivarlo per tutte le sessioni, impostare editor.experimentalScreenReader su true.", - "experimentalScreenReaderSessionOn": "Il supporto per l'utilità per la lettura dello schermo sperimentale è attivato per questa sessione. Per attivare/disattivare questo comportamento, premere {0}.", - "experimentalScreenReaderSessionOnNoKb": "Il supporto per l'utilità per la lettura dello schermo sperimentale è attivato per questa sessione. Il comando {0} non può essere attualmente attivato con un tasto di scelta rapida.", "introMsg": "Grazie per aver provato le opzioni di accessibilità sperimentali di Visual Studio Code.", "outroMsg": "Per chiudere questa descrizione comando e tornare all'editor, premere ESC.", "status": "Stato:", diff --git a/i18n/jpn/src/vs/editor/contrib/accessibility/browser/accessibility.i18n.json b/i18n/jpn/src/vs/editor/contrib/accessibility/browser/accessibility.i18n.json index 5c824daca9c..e8a675d3a8f 100644 --- a/i18n/jpn/src/vs/editor/contrib/accessibility/browser/accessibility.i18n.json +++ b/i18n/jpn/src/vs/editor/contrib/accessibility/browser/accessibility.i18n.json @@ -5,11 +5,6 @@ // Do not edit this file. It is machine generated. { "ShowAccessibilityHelpAction": "アクセシビリティのヘルプを表示します", - "experimentalScreenReaderOptsOn": "editor.experimentalScreenReader 設定キーによって、実験用スクリーン リーダーのサポートがオンになっています。", - "experimentalScreenReaderSessionOff": "実験用スクリーン リーダーのサポートがオフになっています。{0} を押してこのセッションでオンにするか、editor.experimentalScreenReader 設定を true に構成して、すべてのセッションでオンになるようにしてください。", - "experimentalScreenReaderSessionOffNoKb": "実験用スクリーン リーダーのサポートがオフになっています。コマンド {0} は、キー バインドでは現在トリガーできません。editor.experimentalScreenReader 設定を true に構成して、すべてのセッションでオンになるようにしてください。", - "experimentalScreenReaderSessionOn": "実験用スクリーン リーダーのサポートがこのセッションではオンになっています。{0} を押すと、この動作を切り替えます。", - "experimentalScreenReaderSessionOnNoKb": "実験用スクリーン リーダーのサポートがこのセッションではオンになっています。コマンド {0} は、キー バインドでは現在トリガーできません。", "introMsg": "VS Code の実験用アクセシビリティ オプションをご利用いただき、ありがとうございます。", "outroMsg": "Esc キーを押すと、ヒントを消してエディターに戻ることができます。", "status": "ステータス:", diff --git a/i18n/kor/src/vs/editor/contrib/accessibility/browser/accessibility.i18n.json b/i18n/kor/src/vs/editor/contrib/accessibility/browser/accessibility.i18n.json index ec3cf164e99..35724c7bae0 100644 --- a/i18n/kor/src/vs/editor/contrib/accessibility/browser/accessibility.i18n.json +++ b/i18n/kor/src/vs/editor/contrib/accessibility/browser/accessibility.i18n.json @@ -5,11 +5,6 @@ // Do not edit this file. It is machine generated. { "ShowAccessibilityHelpAction": "접근성 도움말 표시", - "experimentalScreenReaderOptsOn": "editor.experimentalScreenReader 설정 키로 인해 실험적 화면 판독기 지원이 켜졌습니다.", - "experimentalScreenReaderSessionOff": "실험적 화면 판독기 지원이 꺼져 있습니다. {0}을(를) 눌러서 이 세션에 대해 이 지원을 켜거나 editor.experimentalScreenReader 설정을 true로 구성하여 모든 세션에 대해 지원을 켜세요.", - "experimentalScreenReaderSessionOffNoKb": "실험적 화면 판독기 지원이 꺼져 있습니다. {0} 명령은 현재 키 바인딩으로 트리거할 수 없습니다. editor.experimentalScreenReader 설정을 true로 구성하여 모든 세션에 대해 이 지원을 켜세요.", - "experimentalScreenReaderSessionOn": "이 세션에 대해 실험적 화면 판독기 지원이 켜져 있습니다. {0}을(를) 눌러서 이 동작을 설정/해제합니다.", - "experimentalScreenReaderSessionOnNoKb": "이 세션에 대해 실험적 화면 판독기 지원이 켜져 있습니다. {0} 명령은 현재 키 바인딩으로 트리거할 수 없습니다.", "introMsg": "VS Code의 실험적 접근성 옵션을 사용해 주셔서 감사합니다.", "outroMsg": "이 도구 설명을 해제하고 Esc 키를 눌러서 편집기로 돌아갈 수 있습니다.", "status": "상태:", From 6519e4c30da1e0c04dd2190f11f71b8c99054640 Mon Sep 17 00:00:00 2001 From: Otger Date: Thu, 28 Apr 2016 16:57:55 +0200 Subject: [PATCH 028/297] Added .inl file extension to C++ language --- extensions/cpp/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/cpp/package.json b/extensions/cpp/package.json index 66a9a64a40f..d66e6415a28 100644 --- a/extensions/cpp/package.json +++ b/extensions/cpp/package.json @@ -12,7 +12,7 @@ }, { "id": "cpp", - "extensions": [ ".cpp", ".cc", ".cxx", ".hpp", ".hh", ".hxx", ".h", ".mm", ".ino" ], + "extensions": [ ".cpp", ".cc", ".cxx", ".hpp", ".hh", ".hxx", ".h", ".mm", ".ino", ".inl" ], "aliases": [ "C++", "Cpp", "cpp"], "configuration": "./cpp.configuration.json" }], From 20180be747e170824ad54d4e58569ae204cb73a8 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 4 May 2016 08:32:47 +0200 Subject: [PATCH 029/297] show rename widget on top of peek widget, fixes #6075 --- src/vs/editor/contrib/rename/browser/rename.css | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vs/editor/contrib/rename/browser/rename.css b/src/vs/editor/contrib/rename/browser/rename.css index eff77813b26..bf0f5e360c7 100644 --- a/src/vs/editor/contrib/rename/browser/rename.css +++ b/src/vs/editor/contrib/rename/browser/rename.css @@ -9,6 +9,7 @@ .monaco-editor .rename-box { box-shadow: 0 2px 8px #A8A8A8; + z-index: 1; color: inherit; } From cff665d10aca1fabd26a7993a1ef24bcb7835c06 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 4 May 2016 08:40:03 +0200 Subject: [PATCH 030/297] :lipstick: renames in rename --- src/vs/editor/browser/editor.all.ts | 2 +- .../editor/contrib/rename/browser/{rename2.ts => rename.ts} | 1 - .../rename/browser/{rename.css => renameInputField.css} | 4 ---- src/vs/editor/contrib/rename/browser/renameInputField.ts | 2 +- 4 files changed, 2 insertions(+), 7 deletions(-) rename src/vs/editor/contrib/rename/browser/{rename2.ts => rename.ts} (99%) rename src/vs/editor/contrib/rename/browser/{rename.css => renameInputField.css} (91%) diff --git a/src/vs/editor/browser/editor.all.ts b/src/vs/editor/browser/editor.all.ts index b1c81d71467..8bb01e10057 100644 --- a/src/vs/editor/browser/editor.all.ts +++ b/src/vs/editor/browser/editor.all.ts @@ -30,7 +30,7 @@ import 'vs/editor/contrib/outlineMarker/browser/outlineMarker'; import 'vs/editor/contrib/parameterHints/browser/parameterHints'; import 'vs/editor/contrib/quickFix/browser/quickFix'; import 'vs/editor/contrib/referenceSearch/browser/referenceSearch'; -import 'vs/editor/contrib/rename/browser/rename2'; +import 'vs/editor/contrib/rename/browser/rename'; import 'vs/editor/contrib/smartSelect/common/smartSelect'; import 'vs/editor/contrib/smartSelect/common/jumpToBracket'; import 'vs/editor/contrib/snippet/common/snippet'; diff --git a/src/vs/editor/contrib/rename/browser/rename2.ts b/src/vs/editor/contrib/rename/browser/rename.ts similarity index 99% rename from src/vs/editor/contrib/rename/browser/rename2.ts rename to src/vs/editor/contrib/rename/browser/rename.ts index eabecbe20f8..1f25fd5f4ac 100644 --- a/src/vs/editor/contrib/rename/browser/rename2.ts +++ b/src/vs/editor/contrib/rename/browser/rename.ts @@ -5,7 +5,6 @@ 'use strict'; -import 'vs/css!./rename'; import * as nls from 'vs/nls'; import {isPromiseCanceledError} from 'vs/base/common/errors'; import {KeyMod, KeyCode} from 'vs/base/common/keyCodes'; diff --git a/src/vs/editor/contrib/rename/browser/rename.css b/src/vs/editor/contrib/rename/browser/renameInputField.css similarity index 91% rename from src/vs/editor/contrib/rename/browser/rename.css rename to src/vs/editor/contrib/rename/browser/renameInputField.css index bf0f5e360c7..9dc105c6ef6 100644 --- a/src/vs/editor/contrib/rename/browser/rename.css +++ b/src/vs/editor/contrib/rename/browser/renameInputField.css @@ -3,10 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -.monaco-editor .word-level-progress { - font-style: italic; -} - .monaco-editor .rename-box { box-shadow: 0 2px 8px #A8A8A8; z-index: 1; diff --git a/src/vs/editor/contrib/rename/browser/renameInputField.ts b/src/vs/editor/contrib/rename/browser/renameInputField.ts index 1be1181db2c..79dbc76b870 100644 --- a/src/vs/editor/contrib/rename/browser/renameInputField.ts +++ b/src/vs/editor/contrib/rename/browser/renameInputField.ts @@ -5,7 +5,7 @@ 'use strict'; -import 'vs/css!./rename'; +import 'vs/css!./renameInputField'; import {localize} from 'vs/nls'; import {canceled} from 'vs/base/common/errors'; import {IDisposable, dispose} from 'vs/base/common/lifecycle'; From 0773b92c0ca14a47244c23b8ebe7e8f9f19abfcd Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 4 May 2016 09:00:29 +0200 Subject: [PATCH 031/297] fix another keybinding#invokeHandler regression which happens when having a constraint defined... --- src/vs/platform/keybinding/common/keybindingsRegistry.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/platform/keybinding/common/keybindingsRegistry.ts b/src/vs/platform/keybinding/common/keybindingsRegistry.ts index 6bbd8854dbf..03aa396a3c3 100644 --- a/src/vs/platform/keybinding/common/keybindingsRegistry.ts +++ b/src/vs/platform/keybinding/common/keybindingsRegistry.ts @@ -116,9 +116,9 @@ class KeybindingsRegistryImpl implements IKeybindingsRegistry { for (let arg of description.args) { constraints.push(arg.constraint); } - handler = function(accesor, args) { + handler = function (accesor, ...args: any[]) { validateConstraints(args, constraints); - return desc.handler(accesor, args); + return desc.handler(accesor, ...args); }; } From 1d5fdb1a03ffc168f802655437866a5444911225 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Wed, 4 May 2016 09:33:48 +0200 Subject: [PATCH 032/297] earlier .build/electron test --- scripts/code-cli.sh | 2 +- scripts/code.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/code-cli.sh b/scripts/code-cli.sh index 5c8862d2062..17bd0929f62 100755 --- a/scripts/code-cli.sh +++ b/scripts/code-cli.sh @@ -14,7 +14,7 @@ function code() { test -d node_modules || ./scripts/npm.sh install # Get electron - ./node_modules/.bin/gulp electron + test -d .build/electron || ./node_modules/.bin/gulp electron # Build test -d out || ./node_modules/.bin/gulp compile diff --git a/scripts/code.sh b/scripts/code.sh index 18a8c3a9ed4..3bcf525ba06 100755 --- a/scripts/code.sh +++ b/scripts/code.sh @@ -14,7 +14,7 @@ function code() { test -d node_modules || ./scripts/npm.sh install # Get electron - ./node_modules/.bin/gulp electron + test -d .build/electron || ./node_modules/.bin/gulp electron # Build test -d out || ./node_modules/.bin/gulp compile From f348d02a50a5315750a39540ffc8a6f86479485b Mon Sep 17 00:00:00 2001 From: isidor Date: Wed, 4 May 2016 09:54:06 +0200 Subject: [PATCH 033/297] debug: show 'Thread' on hover fixes #5807 --- src/vs/workbench/parts/debug/browser/debugViewer.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vs/workbench/parts/debug/browser/debugViewer.ts b/src/vs/workbench/parts/debug/browser/debugViewer.ts index 4cb192f2915..48833ac4838 100644 --- a/src/vs/workbench/parts/debug/browser/debugViewer.ts +++ b/src/vs/workbench/parts/debug/browser/debugViewer.ts @@ -355,6 +355,7 @@ export class CallStackRenderer implements tree.IRenderer { } private renderThread(thread: debug.IThread, data: IThreadTemplateData): void { + data.thread.title = nls.localize('thread', "Thread"); data.name.textContent = thread.name; data.stateLabel.textContent = thread.stopped ? nls.localize('paused', "paused") : nls.localize('running', "running"); } From e23fe6364e271d0c071395cb55bbea80d580316e Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 4 May 2016 09:22:20 +0200 Subject: [PATCH 034/297] make zone widget abstract --- .../contrib/gotoError/browser/gotoError.ts | 2 +- .../browser/referenceSearchWidget.ts | 2 +- .../zoneWidget/browser/peekViewWidget.ts | 4 ++-- .../contrib/zoneWidget/browser/zoneWidget.ts | 20 +++++++++---------- .../parts/debug/browser/breakpointWidget.ts | 2 +- 5 files changed, 14 insertions(+), 16 deletions(-) diff --git a/src/vs/editor/contrib/gotoError/browser/gotoError.ts b/src/vs/editor/contrib/gotoError/browser/gotoError.ts index 8049773f47c..fc4dd5a2a4c 100644 --- a/src/vs/editor/contrib/gotoError/browser/gotoError.ts +++ b/src/vs/editor/contrib/gotoError/browser/gotoError.ts @@ -214,7 +214,7 @@ class MarkerNavigationWidget extends ZoneWidget { this._wireModelAndView(); } - public fillContainer(container: HTMLElement): void { + protected _fillContainer(container: HTMLElement): void { this._container = container; dom.addClass(this._container, 'marker-widget'); diff --git a/src/vs/editor/contrib/referenceSearch/browser/referenceSearchWidget.ts b/src/vs/editor/contrib/referenceSearch/browser/referenceSearchWidget.ts index 7842be41c70..4a27090402b 100644 --- a/src/vs/editor/contrib/referenceSearch/browser/referenceSearchWidget.ts +++ b/src/vs/editor/contrib/referenceSearch/browser/referenceSearchWidget.ts @@ -572,7 +572,7 @@ export class ReferenceWidget extends PeekViewWidget { this._lastHeight = height; } - public onWidth(widthInPixel: number): void { + public _onWidth(widthInPixel: number): void { this._sash.width = widthInPixel; this._preview.layout(); } diff --git a/src/vs/editor/contrib/zoneWidget/browser/peekViewWidget.ts b/src/vs/editor/contrib/zoneWidget/browser/peekViewWidget.ts index 1f31c132b36..fd4714d808d 100644 --- a/src/vs/editor/contrib/zoneWidget/browser/peekViewWidget.ts +++ b/src/vs/editor/contrib/zoneWidget/browser/peekViewWidget.ts @@ -80,7 +80,7 @@ export class PeekViewWidget extends ZoneWidget implements IPeekViewService { super.show(where, heightInLines); } - public fillContainer(container: HTMLElement): void { + protected _fillContainer(container: HTMLElement): void { $(container).addClass('peekview-widget'); this._headElement = $('.head').getHTMLElement(); @@ -140,7 +140,7 @@ export class PeekViewWidget extends ZoneWidget implements IPeekViewService { // implement me } - public doLayout(heightInPixel: number, widthInPixel: number): void { + public _doLayout(heightInPixel: number, widthInPixel: number): void { if (heightInPixel < 0) { // Looks like the view zone got folded away! diff --git a/src/vs/editor/contrib/zoneWidget/browser/zoneWidget.ts b/src/vs/editor/contrib/zoneWidget/browser/zoneWidget.ts index 4d4fd7134f7..f571382404d 100644 --- a/src/vs/editor/contrib/zoneWidget/browser/zoneWidget.ts +++ b/src/vs/editor/contrib/zoneWidget/browser/zoneWidget.ts @@ -89,7 +89,7 @@ class OverlayWidgetDelegate implements IOverlayWidget { } -export class ZoneWidget implements IHorizontalSashLayoutProvider { +export abstract class ZoneWidget implements IHorizontalSashLayoutProvider { private _viewZone: ViewZoneDelegate = null; private _overlayWidget: OverlayWidgetDelegate = null; @@ -114,7 +114,7 @@ export class ZoneWidget implements IHorizontalSashLayoutProvider { this._disposables.add(this.editor.addListener2(EventType.EditorLayout, (info: IEditorLayoutInfo) => { var width = this._getWidth(info); this.domNode.style.width = width + 'px'; - this.onWidth(width); + this._onWidth(width); })); } @@ -126,7 +126,7 @@ export class ZoneWidget implements IHorizontalSashLayoutProvider { this.container = document.createElement('div'); dom.addClass(this.container, 'zone-widget-container'); this.domNode.appendChild(this.container); - this.fillContainer(this.container); + this._fillContainer(this.container); this._initSash(); } @@ -144,7 +144,7 @@ export class ZoneWidget implements IHorizontalSashLayoutProvider { let containerHeight = height - this._decoratingElementsHeight(); this.container.style.height = `${containerHeight}px`; - this.doLayout(containerHeight, this._getWidth()); + this._doLayout(containerHeight, this._getWidth()); this._resizeSash.layout(); } @@ -248,7 +248,7 @@ export class ZoneWidget implements IHorizontalSashLayoutProvider { this.container.style.overflow = 'hidden'; - this.doLayout(containerHeight, width); + this._doLayout(containerHeight, width); this.editor.setSelection(where); @@ -276,15 +276,13 @@ export class ZoneWidget implements IHorizontalSashLayoutProvider { } } - public fillContainer(container: HTMLElement): void { + protected abstract _fillContainer(container: HTMLElement): void; + + protected _onWidth(widthInPixel: number): void { // implement in subclass } - public onWidth(widthInPixel: number): void { - // implement in subclass - } - - public doLayout(heightInPixel: number, widthInPixel: number): void { + protected _doLayout(heightInPixel: number, widthInPixel: number): void { // implement in subclass } diff --git a/src/vs/workbench/parts/debug/browser/breakpointWidget.ts b/src/vs/workbench/parts/debug/browser/breakpointWidget.ts index d3bf0ac60eb..d54b89463ca 100644 --- a/src/vs/workbench/parts/debug/browser/breakpointWidget.ts +++ b/src/vs/workbench/parts/debug/browser/breakpointWidget.ts @@ -58,7 +58,7 @@ export class BreakpointWidget extends ZoneWidget { BreakpointWidget.INSTANCE.show({ lineNumber, column: 1 }, 2); } - public fillContainer(container: HTMLElement): void { + protected _fillContainer(container: HTMLElement): void { dom.addClass(container, 'breakpoint-widget'); const uri = this.editor.getModel().getAssociatedResource(); const breakpoint = this.debugService.getModel().getBreakpoints().filter(bp => bp.lineNumber === this.lineNumber && bp.source.uri.toString() === uri.toString()).pop(); From 43f6ac04d455c2219d1101b5e302face196dd09b Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 4 May 2016 09:55:27 +0200 Subject: [PATCH 035/297] some clean up and storage of peek view layout data --- .../browser/referenceSearch.ts | 37 ++++++------ .../browser/referenceSearchWidget.ts | 59 +++++++++---------- .../zoneWidget/browser/peekViewWidget.ts | 10 +--- .../contrib/zoneWidget/browser/zoneWidget.ts | 8 +-- 4 files changed, 53 insertions(+), 61 deletions(-) diff --git a/src/vs/editor/contrib/referenceSearch/browser/referenceSearch.ts b/src/vs/editor/contrib/referenceSearch/browser/referenceSearch.ts index 87c5439f59a..f664a9ff8bb 100644 --- a/src/vs/editor/contrib/referenceSearch/browser/referenceSearch.ts +++ b/src/vs/editor/contrib/referenceSearch/browser/referenceSearch.ts @@ -19,6 +19,7 @@ import {KeybindingsRegistry} from 'vs/platform/keybinding/common/keybindingsRegi import {IMessageService} from 'vs/platform/message/common/message'; import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry'; import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace'; +import {IStorageService} from 'vs/platform/storage/common/storage'; import {Position} from 'vs/editor/common/core/position'; import {Range} from 'vs/editor/common/core/range'; import {EditorAction} from 'vs/editor/common/editorAction'; @@ -31,7 +32,7 @@ import {EditorBrowserRegistry} from 'vs/editor/browser/editorBrowserExtensions'; import {IPeekViewService, getOuterEditor} from 'vs/editor/contrib/zoneWidget/browser/peekViewWidget'; import {findReferences} from '../common/referenceSearch'; import {EventType, ReferencesModel} from './referenceSearchModel'; -import {ReferenceWidget} from './referenceSearchWidget'; +import {ReferenceWidget, LayoutData} from './referenceSearchWidget'; import {ServicesAccessor} from 'vs/platform/instantiation/common/instantiation'; export class FindReferencesController implements editorCommon.IEditorContribution { @@ -51,7 +52,6 @@ export class FindReferencesController implements editorCommon.IEditorContributio private instantiationService: IInstantiationService; private contextService: IWorkspaceContextService; private peekViewService: IPeekViewService; - private keybindingService: IKeybindingService; private _startTime: number = -1; private _referenceSearchVisible: IKeybindingContextKey; @@ -60,13 +60,15 @@ export class FindReferencesController implements editorCommon.IEditorContributio return editor.getContribution(FindReferencesController.ID); } - public constructor(editor: ICodeEditor, + public constructor( + editor: ICodeEditor, @IEditorService editorService: IEditorService, @ITelemetryService telemetryService: ITelemetryService, @IMessageService messageService: IMessageService, @IInstantiationService instantiationService: IInstantiationService, @IKeybindingService keybindingService: IKeybindingService, @IWorkspaceContextService contextService: IWorkspaceContextService, + @IStorageService private _storageService: IStorageService, @optional(IPeekViewService) peekViewService: IPeekViewService ) { this._requestIdPool = 0; @@ -77,7 +79,6 @@ export class FindReferencesController implements editorCommon.IEditorContributio this.instantiationService = instantiationService; this.peekViewService = peekViewService; this.contextService = contextService; - this.keybindingService = keybindingService; this._modelRevealing = false; this._editor = editor; this._referenceSearchVisible = keybindingService.createKey(CONTEXT_REFERENCE_SEARCH_VISIBLE, false); @@ -123,19 +124,19 @@ export class FindReferencesController implements editorCommon.IEditorContributio this.clear(); } })); - - this._widget = new ReferenceWidget(this.editorService, this.keybindingService, this.contextService, this.instantiationService, this._editor); + const storageKey = 'peekViewLayout'; + const data = JSON.parse(this._storageService.get(storageKey, undefined, '{}')); + this._widget = new ReferenceWidget(this._editor, data, this.editorService, this.contextService, this.instantiationService); this._widget.setTitle(nls.localize('labelLoading', "Loading...")); - this._widget.show(range, 18); + this._widget.show(range); this._callOnClear.push(this._widget.onDidClose(() => { + referencesPromise.cancel(); + + this._storageService.store(storageKey, JSON.stringify(this._widget.layoutData)); this._widget = null; this.clear(); }).dispose); - this._callOnClear.push(() => { - referencesPromise.cancel(); - }); - this._callOnClear.push(this._widget.onDidDoubleClick(event => { if(!event.reference) { @@ -199,7 +200,7 @@ export class FindReferencesController implements editorCommon.IEditorContributio return; } this._modelRevealing = false; - this._widget.show(this._model.currentReference.range, 18); + this._widget.show(this._model.currentReference.range); this._widget.focus(); }, (err) => { this._modelRevealing = false; @@ -235,12 +236,6 @@ export class FindReferencesController implements editorCommon.IEditorContributio this._startTime = -1; } - this._referenceSearchVisible.reset(); - - cAll(this._callOnClear); - - this._model = null; - var result = false; if(this._widget) { this._widget.dispose(); @@ -248,6 +243,12 @@ export class FindReferencesController implements editorCommon.IEditorContributio result = true; } + this._referenceSearchVisible.reset(); + + cAll(this._callOnClear); + + this._model = null; + this._editor.focus(); this._requestIdPool += 1; // Cancel pending requests return result; diff --git a/src/vs/editor/contrib/referenceSearch/browser/referenceSearchWidget.ts b/src/vs/editor/contrib/referenceSearch/browser/referenceSearchWidget.ts index 4a27090402b..5a2ecb7ee09 100644 --- a/src/vs/editor/contrib/referenceSearch/browser/referenceSearchWidget.ts +++ b/src/vs/editor/contrib/referenceSearch/browser/referenceSearchWidget.ts @@ -29,7 +29,6 @@ import {Tree} from 'vs/base/parts/tree/browser/treeImpl'; import {IEditorService} from 'vs/platform/editor/common/editor'; import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation'; import {ServiceCollection} from 'vs/platform/instantiation/common/serviceCollection'; -import {IKeybindingService} from 'vs/platform/keybinding/common/keybindingService'; import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace'; import {DefaultConfig} from 'vs/editor/common/config/defaultConfig'; import {Range} from 'vs/editor/common/core/range'; @@ -423,6 +422,15 @@ class VSash { let right = 100 - left; return [`${left}%`, `${right}%`]; } + + get ratio() { + return this._ratio; + } +} + +export interface LayoutData { + ratio: number; + heightInLines: number; } /** @@ -432,10 +440,6 @@ export class ReferenceWidget extends PeekViewWidget { public static INNER_EDITOR_CONTEXT_KEY = 'inReferenceSearchEditor'; - private _editorService: IEditorService; - private _contextService: IWorkspaceContextService; - private _instantiationService: IInstantiationService; - private _decorationsManager: DecorationsManager; private _model: ReferencesModel; private _callOnModel: IDisposable[] = []; @@ -449,28 +453,16 @@ export class ReferenceWidget extends PeekViewWidget { private _previewContainer: Builder; private _messageContainer: Builder; - private _lastHeight: string; - constructor( - editorService: IEditorService, - keybindingService: IKeybindingService, - contextService: IWorkspaceContextService, - instantiationService: IInstantiationService, - editor: ICodeEditor + editor: ICodeEditor, + public layoutData: LayoutData, + private _editorService: IEditorService, + private _contextService: IWorkspaceContextService, + private _instantiationService: IInstantiationService ) { - super(editor, keybindingService, ReferenceWidget.INNER_EDITOR_CONTEXT_KEY, { frameColor: '#007ACC', showFrame: false, showArrow: true, isResizeable: true }); - this._editorService = editorService; - this._contextService = contextService; - this._instantiationService = instantiationService.createChild(new ServiceCollection([IPeekViewService, this])); - - this._tree = null; - this._treeContainer = null; - - this._preview = null; - this._previewContainer = null; - - this._lastHeight = null; + super(editor, ReferenceWidget.INNER_EDITOR_CONTEXT_KEY, { frameColor: '#007ACC', showFrame: false, showArrow: true, isResizeable: true }); + this._instantiationService = this._instantiationService.createChild(new ServiceCollection([IPeekViewService, this])); this.create(); } @@ -484,6 +476,10 @@ export class ReferenceWidget extends PeekViewWidget { return this._onDidDoubleClick.event; } + show(where: editorCommon.IRange) { + super.show(where, this.layoutData.heightInLines || 18); + } + protected _onTitleClick(e: MouseEvent): void { if (!this._preview || !this._preview.getModel()) { return; @@ -520,13 +516,14 @@ export class ReferenceWidget extends PeekViewWidget { }); // sash - this._sash = new VSash(containerElement, .8); + this._sash = new VSash(containerElement, this.layoutData.ratio || .8); this._sash.onDidChangePercentages(() => { let [left, right] = this._sash.percentages; this._previewContainer.style({ width: left}); this._treeContainer.style({ width: right }); this._preview.layout(); this._tree.layout(); + this.layoutData.ratio = this._sash.ratio; }); // tree @@ -553,23 +550,23 @@ export class ReferenceWidget extends PeekViewWidget { super._doLayoutBody(heightInPixel, widthInPixel); const height = heightInPixel + 'px'; - if (height === this._lastHeight) { - return; - } - this._sash.height = heightInPixel; this._sash.width = widthInPixel; // set height/width const [left, right] = this._sash.percentages; - this._previewContainer.style({ height, width: left}); + this._previewContainer.style({ height, width: left }); this._treeContainer.style({ height, width: right }); // forward this._tree.layout(heightInPixel); this._preview.layout(); - this._lastHeight = height; + // store layout data + this.layoutData = { + heightInLines: this._viewZone.heightInLines, + ratio: this._sash.ratio + }; } public _onWidth(widthInPixel: number): void { diff --git a/src/vs/editor/contrib/zoneWidget/browser/peekViewWidget.ts b/src/vs/editor/contrib/zoneWidget/browser/peekViewWidget.ts index fd4714d808d..4b31a630ea0 100644 --- a/src/vs/editor/contrib/zoneWidget/browser/peekViewWidget.ts +++ b/src/vs/editor/contrib/zoneWidget/browser/peekViewWidget.ts @@ -14,7 +14,6 @@ import Event, {Emitter} from 'vs/base/common/event'; import * as dom from 'vs/base/browser/dom'; import {ActionBar} from 'vs/base/browser/ui/actionbar/actionbar'; import {ServiceIdentifier, ServicesAccessor, createDecorator} from 'vs/platform/instantiation/common/instantiation'; -import {IKeybindingService} from 'vs/platform/keybinding/common/keybindingService'; import {ICommonCodeEditor} from 'vs/editor/common/editorCommon'; import {ICodeEditorService} from 'vs/editor/common/services/codeEditorService'; import {ICodeEditor} from 'vs/editor/browser/editorBrowser'; @@ -27,7 +26,6 @@ export interface IPeekViewService { serviceId: ServiceIdentifier; isActive: boolean; contextKey: string; - getActiveWidget(): PeekViewWidget; } export function getOuterEditor(accessor: ServicesAccessor, args: any): ICommonCodeEditor { @@ -53,7 +51,7 @@ export class PeekViewWidget extends ZoneWidget implements IPeekViewService { protected _actionbarWidget: ActionBar; protected _bodyElement: HTMLDivElement; - constructor(editor: ICodeEditor, keybindingService: IKeybindingService, contextKey: string, options: IOptions = {}) { + constructor(editor: ICodeEditor, contextKey: string, options: IOptions = {}) { super(editor, options); this.contextKey = contextKey; } @@ -61,6 +59,7 @@ export class PeekViewWidget extends ZoneWidget implements IPeekViewService { public dispose(): void { this._isActive = false; super.dispose(); + this._onDidClose.fire(this); } public get onDidClose(): Event { @@ -71,10 +70,6 @@ export class PeekViewWidget extends ZoneWidget implements IPeekViewService { return this._isActive; } - public getActiveWidget(): PeekViewWidget { - return this; - } - public show(where: any, heightInLines: number): void { this._isActive = true; super.show(where, heightInLines); @@ -110,7 +105,6 @@ export class PeekViewWidget extends ZoneWidget implements IPeekViewService { this._actionbarWidget.push(new Action('peekview.close', nls.localize('label.close', "Close"), 'close-peekview-action', true, () => { this.dispose(); - this._onDidClose.fire(this); return null; }), { label: false, icon: true }); } diff --git a/src/vs/editor/contrib/zoneWidget/browser/zoneWidget.ts b/src/vs/editor/contrib/zoneWidget/browser/zoneWidget.ts index f571382404d..93b16631803 100644 --- a/src/vs/editor/contrib/zoneWidget/browser/zoneWidget.ts +++ b/src/vs/editor/contrib/zoneWidget/browser/zoneWidget.ts @@ -91,10 +91,10 @@ class OverlayWidgetDelegate implements IOverlayWidget { export abstract class ZoneWidget implements IHorizontalSashLayoutProvider { - private _viewZone: ViewZoneDelegate = null; - private _overlayWidget: OverlayWidgetDelegate = null; - private _resizeSash: Sash; - private _disposables = new Disposables(); + protected _viewZone: ViewZoneDelegate = null; + protected _overlayWidget: OverlayWidgetDelegate = null; + protected _resizeSash: Sash; + protected _disposables = new Disposables(); public container: HTMLElement = null; public domNode: HTMLElement; From e807b1caa92c617f8787ee589b88ec19647063ad Mon Sep 17 00:00:00 2001 From: isidor Date: Wed, 4 May 2016 10:02:29 +0200 Subject: [PATCH 036/297] debug: reduce min panel height fixes #6085 --- src/vs/workbench/browser/layout.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/browser/layout.ts b/src/vs/workbench/browser/layout.ts index 43d9db77cd4..12eaa95e436 100644 --- a/src/vs/workbench/browser/layout.ts +++ b/src/vs/workbench/browser/layout.ts @@ -20,7 +20,7 @@ import {IThemeService} from 'vs/workbench/services/themes/common/themeService'; import {IDisposable, dispose} from 'vs/base/common/lifecycle'; const DEFAULT_MIN_PART_WIDTH = 170; -const DEFAULT_MIN_PANEL_PART_HEIGHT = 170; +const DEFAULT_MIN_PANEL_PART_HEIGHT = 77; const DEFAULT_MIN_EDITOR_PART_HEIGHT = 170; const HIDE_SIDEBAR_WIDTH_THRESHOLD = 50; const HIDE_PANEL_HEIGHT_THRESHOLD = 50; From 0dfaf2cca33f9378bd3b0e1ec6f2c51bda648334 Mon Sep 17 00:00:00 2001 From: isidor Date: Wed, 4 May 2016 10:59:20 +0200 Subject: [PATCH 037/297] debug: transition to running state after launch / attach also --- .../workbench/parts/debug/electron-browser/debugService.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/parts/debug/electron-browser/debugService.ts b/src/vs/workbench/parts/debug/electron-browser/debugService.ts index f66f571dfb6..6cd2475767e 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugService.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugService.ts @@ -580,6 +580,7 @@ export class DebugService implements debug.IDebugService { glyphMargin: true }); this.inDebugMode.set(true); + this.lazyTransitionToRunningState(); this.telemetryService.publicLog('debugSessionStart', { type: configuration.type, breakpointCount: this.model.getBreakpoints().length, exceptionBreakpoints: this.model.getExceptionBreakpoints(), watchExpressionsCount: this.model.getWatchExpressions().length }); }).then(undefined, (error: any) => { @@ -838,10 +839,10 @@ export class DebugService implements debug.IDebugService { } - private lazyTransitionToRunningState(threadId: number): void { + private lazyTransitionToRunningState(threadId?: number): void { let cancelTransitionToRunningState = false; const toDispose = this.session.onDidStop(e => { - if (e.body.threadId === threadId || e.body.allThreadsStopped) { + if (e.body.threadId === threadId || e.body.allThreadsStopped || !threadId) { cancelTransitionToRunningState = true; } }); From e9f9aad3f83b7982bd890b96e3d533a094c3cc63 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Wed, 4 May 2016 10:12:49 +0200 Subject: [PATCH 038/297] fix bad JS --- src/main.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main.js b/src/main.js index 2dd8fe2f569..20e7ddfa8a2 100644 --- a/src/main.js +++ b/src/main.js @@ -50,11 +50,11 @@ function getNLSConfiguration() { if (!locale) { var userData = app.getPath('userData'); - localeConfig = path.join(userData, 'User', 'locale.json'); + var localeConfig = path.join(userData, 'User', 'locale.json'); if (fs.existsSync(localeConfig)) { try { var content = stripComments(fs.readFileSync(localeConfig, 'utf8')); - value = JSON.parse(content).locale; + var value = JSON.parse(content).locale; if (value && typeof value === 'string') { locale = value; } From e634302883c9dc8129d9bd0bf03f6854fd379597 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Wed, 4 May 2016 10:43:55 +0200 Subject: [PATCH 039/297] extract userData path computation --- package.json | 2 +- src/main.js | 18 +++++------------- src/paths.js | 32 ++++++++++++++++++++++++++++++++ src/vs/base/node/paths.ts | 16 ++++++++++++++++ 4 files changed, 54 insertions(+), 14 deletions(-) create mode 100644 src/paths.js create mode 100644 src/vs/base/node/paths.ts diff --git a/package.json b/package.json index 1b90c93744f..937db863ea5 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "Code", + "name": "Code - OSS", "version": "1.1.0", "electronVersion": "0.37.6", "author": { diff --git a/src/main.js b/src/main.js index 20e7ddfa8a2..2009f835604 100644 --- a/src/main.js +++ b/src/main.js @@ -9,6 +9,8 @@ global.vscodeStart = Date.now(); var app = require('electron').app; var fs = require('fs'); var path = require('path'); +var paths = require('./paths'); +var pkg = require('../package.json'); function stripComments(content) { var regexp = /("(?:[^\\\"]*(?:\\.)?)*")|('(?:[^\\\']*(?:\\.)?)*')|(\/\*(?:\r?\n|.)*?\*\/)|(\/{2,}.*?(?:(?:\r?\n)|$))/g; @@ -107,19 +109,9 @@ try { console.error(err); } -// Set path according to being built or not -if (process.env['VSCODE_DEV']) { - var appData = app.getPath('appData'); - app.setPath('userData', path.join(appData, 'Code-Development')); -} - -// Use custom user data dir if specified, required to run as root on Linux -var args = process.argv; -args.forEach(function (arg) { - if (arg.indexOf('--user-data-dir=') === 0) { - app.setPath('userData', arg.split('=')[1]); - } -}); +// Set userData path before app 'ready' event +var userData = paths.getUserDataPath(process.platform, pkg.name, process.argv); +app.setPath('userData', userData); // Mac: when someone drops a file to the not-yet running VSCode, the open-file event fires even before // the app-ready event. We listen very early for open-file and remember this upon startup as path to open. diff --git a/src/paths.js b/src/paths.js new file mode 100644 index 00000000000..33bf3f518e8 --- /dev/null +++ b/src/paths.js @@ -0,0 +1,32 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +var minimist = require('minimist'); +var path = require('path'); +var os = require('os'); + +function getAppDataPath(platform) { + switch (platform) { + case 'win32': return process.env['APPDATA']; + case 'darwin': return path.join(os.homedir(), 'Library', 'Application Support'); + case 'linux': return process.env['XDG_CONFIG_HOME'] || path.join(os.homedir(), '.config'); + default: throw new Error('Platform not supported'); + } +} + +function getUserDataPath(platform, appName, args) { + var argv = minimist(args, { string: ['user-data-dir'] }); + var userDataDir = argv['user-data-dir']; + var appData = getAppDataPath(platform); + + if (userDataDir) { + return userDataDir; + } + + return path.join(appData, appName); +} + +exports.getAppDataPath = getAppDataPath; +exports.getUserDataPath = getUserDataPath; \ No newline at end of file diff --git a/src/vs/base/node/paths.ts b/src/vs/base/node/paths.ts new file mode 100644 index 00000000000..8cd14b49f6f --- /dev/null +++ b/src/vs/base/node/paths.ts @@ -0,0 +1,16 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import uri from 'vs/base/common/uri'; + +interface IPaths { + getAppDataPath(platform: string): string; + getUserDataPath(platform: string, appName: string, args: string[]): string; +} + +const pathsPath = uri.parse(require.toUrl('paths')).fsPath; +const paths = require.__$__nodeRequire(pathsPath); +export const getAppDataPath = paths.getAppDataPath; +export const getUserDataPath = paths.getUserDataPath; From b35c322fdaf539b676db0638e9cc53163bdb2a92 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Wed, 4 May 2016 10:59:34 +0200 Subject: [PATCH 040/297] dont use spaces in package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 937db863ea5..d51c69c6c29 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "Code - OSS", + "name": "Code-OSS", "version": "1.1.0", "electronVersion": "0.37.6", "author": { From 3e8dab98c7f6b956eeff1b8e9af4b95baac3b665 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Wed, 4 May 2016 11:01:10 +0200 Subject: [PATCH 041/297] fix build --- build/gulpfile.vscode.js | 1 + 1 file changed, 1 insertion(+) diff --git a/build/gulpfile.vscode.js b/build/gulpfile.vscode.js index cc799c132ff..532a059f5e4 100644 --- a/build/gulpfile.vscode.js +++ b/build/gulpfile.vscode.js @@ -52,6 +52,7 @@ var vscodeResources = [ 'out-build/cli.js', 'out-build/bootstrap.js', 'out-build/bootstrap-amd.js', + 'out-build/paths.js', 'out-build/vs/**/*.{svg,png,cur}', 'out-build/vs/base/node/{stdForkStart.js,terminateProcess.sh}', 'out-build/vs/base/worker/workerMainCompatibility.html', From bfec11d7039cf00ff057a55741ae5347d3fa7641 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Wed, 4 May 2016 11:08:48 +0200 Subject: [PATCH 042/297] use lowercase --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d51c69c6c29..d3457292405 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "Code-OSS", + "name": "code-oss-dev", "version": "1.1.0", "electronVersion": "0.37.6", "author": { From cb9b1852379cd39cc36347cb9bde3e6213cdf037 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Wed, 4 May 2016 11:16:02 +0200 Subject: [PATCH 043/297] faster code.bat --- scripts/code.bat | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/code.bat b/scripts/code.bat index 43e3f71cf51..5386769edc2 100644 --- a/scripts/code.bat +++ b/scripts/code.bat @@ -9,7 +9,7 @@ pushd %~dp0\.. if not exist node_modules call .\scripts\npm.bat install :: Get electron -node .\node_modules\gulp\bin\gulp.js electron +if not exist .build\electron node .\node_modules\gulp\bin\gulp.js electron :: Build if not exist out node .\node_modules\gulp\bin\gulp.js compile From c7bc47ac58233b2832547e8a428db142a98030d2 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 4 May 2016 11:49:42 +0200 Subject: [PATCH 044/297] add new config option 'editor.dismissPeekOnEsc' to control ESC when peek shows, #5120 --- .../common/config/commonEditorConfig.ts | 5 ++++ .../browser/referenceSearch.ts | 28 +++++++++++++------ 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/src/vs/editor/common/config/commonEditorConfig.ts b/src/vs/editor/common/config/commonEditorConfig.ts index 48d1bc50cb0..dd4e6b5f558 100644 --- a/src/vs/editor/common/config/commonEditorConfig.ts +++ b/src/vs/editor/common/config/commonEditorConfig.ts @@ -944,6 +944,11 @@ let editorConfiguration:IConfigurationNode = { 'default': DefaultConfig.editor.trimAutoWhitespace, 'description': nls.localize('trimAutoWhitespace', "Remove trailing auto inserted whitespace") }, + 'editor.dismissPeekOnEsc' : { + 'type': 'boolean', + 'default': true, + 'description': nls.localize('dismissPeekOnEsc', "Close peek editor when pressing ESC") + }, 'diffEditor.renderSideBySide' : { 'type': 'boolean', 'default': true, diff --git a/src/vs/editor/contrib/referenceSearch/browser/referenceSearch.ts b/src/vs/editor/contrib/referenceSearch/browser/referenceSearch.ts index f664a9ff8bb..05ab600f3eb 100644 --- a/src/vs/editor/contrib/referenceSearch/browser/referenceSearch.ts +++ b/src/vs/editor/contrib/referenceSearch/browser/referenceSearch.ts @@ -14,7 +14,7 @@ import URI from 'vs/base/common/uri'; import {TPromise} from 'vs/base/common/winjs.base'; import {IEditorService} from 'vs/platform/editor/common/editor'; import {IInstantiationService, optional} from 'vs/platform/instantiation/common/instantiation'; -import {ICommandHandler, IKeybindingContextKey, IKeybindingService} from 'vs/platform/keybinding/common/keybindingService'; +import {ICommandHandler, IKeybindingContextKey, IKeybindingService, KbExpr} from 'vs/platform/keybinding/common/keybindingService'; import {KeybindingsRegistry} from 'vs/platform/keybinding/common/keybindingsRegistry'; import {IMessageService} from 'vs/platform/message/common/message'; import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry'; @@ -390,17 +390,29 @@ KeybindingsRegistry.registerCommandDesc({ ] } }); -CommonEditorRegistry.registerEditorCommand('closeReferenceSearch', CommonEditorRegistry.commandWeight(50), { primary: KeyCode.Escape, secondary: [KeyMod.Shift | KeyCode.Escape] }, false, CONTEXT_REFERENCE_SEARCH_VISIBLE, (accessor, editor, args) => { + +function closeActiveReferenceSearch(accessor, args) { var outerEditor = getOuterEditor(accessor, args); if (outerEditor) { var controller = FindReferencesController.getController(outerEditor); controller.closeReferenceSearch(); } +} + +KeybindingsRegistry.registerCommandDesc({ + id: 'closeReferenceSearch', + weight: CommonEditorRegistry.commandWeight(50), + primary: KeyCode.Escape, + secondary: [KeyMod.Shift | KeyCode.Escape], + when: KbExpr.and(KbExpr.has(CONTEXT_REFERENCE_SEARCH_VISIBLE), KbExpr.has('config.editor.dismissPeekOnEsc')), + handler: closeActiveReferenceSearch }); -CommonEditorRegistry.registerEditorCommand('closeReferenceSearchEditor', CommonEditorRegistry.commandWeight(-101), { primary: KeyCode.Escape, secondary: [KeyMod.Shift | KeyCode.Escape] }, false, ReferenceWidget.INNER_EDITOR_CONTEXT_KEY, (accessor, editor, args) => { - var outerEditor = getOuterEditor(accessor, args); - if (outerEditor) { - var controller = FindReferencesController.getController(outerEditor); - controller.closeReferenceSearch(); - } + +KeybindingsRegistry.registerCommandDesc({ + id: 'closeReferenceSearchEditor', + weight: CommonEditorRegistry.commandWeight(-101), + primary: KeyCode.Escape, + secondary: [KeyMod.Shift | KeyCode.Escape], + when: KbExpr.and(KbExpr.has(ReferenceWidget.INNER_EDITOR_CONTEXT_KEY), KbExpr.has('config.editor.dismissPeekOnEsc')), + handler: closeActiveReferenceSearch }); From 1d2706805f905c77458fdcb6e15cb8e9b14cd2ef Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 4 May 2016 12:27:43 +0200 Subject: [PATCH 045/297] fix missing export --- src/vs/editor/contrib/zoneWidget/browser/zoneWidget.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/editor/contrib/zoneWidget/browser/zoneWidget.ts b/src/vs/editor/contrib/zoneWidget/browser/zoneWidget.ts index 93b16631803..554f1b96acc 100644 --- a/src/vs/editor/contrib/zoneWidget/browser/zoneWidget.ts +++ b/src/vs/editor/contrib/zoneWidget/browser/zoneWidget.ts @@ -33,7 +33,7 @@ var defaultOptions: IOptions = { var WIDGET_ID = 'vs.editor.contrib.zoneWidget'; -class ViewZoneDelegate implements IViewZone { +export class ViewZoneDelegate implements IViewZone { public domNode: HTMLElement; public id: number; @@ -65,7 +65,7 @@ class ViewZoneDelegate implements IViewZone { } } -class OverlayWidgetDelegate implements IOverlayWidget { +export class OverlayWidgetDelegate implements IOverlayWidget { private _id: string; private _domNode: HTMLElement; From 4726b2971dcb165f07f125342e806720aac3a34f Mon Sep 17 00:00:00 2001 From: isidor Date: Wed, 4 May 2016 12:50:13 +0200 Subject: [PATCH 046/297] debug: configuration to reveal debug console fixes #5889, fixes #4045 --- src/vs/workbench/parts/debug/common/debug.ts | 1 + .../parts/debug/electron-browser/debugService.ts | 15 ++++++++++----- src/vs/workbench/parts/debug/node/debugAdapter.ts | 5 +++++ 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/parts/debug/common/debug.ts b/src/vs/workbench/parts/debug/common/debug.ts index eef61ebc35e..f0846b866cb 100644 --- a/src/vs/workbench/parts/debug/common/debug.ts +++ b/src/vs/workbench/parts/debug/common/debug.ts @@ -206,6 +206,7 @@ export interface IConfig { sourceMaps?: boolean; outDir?: string; address?: string; + internalConsoleOptions?: string; port?: number; preLaunchTask?: string; externalConsole?: boolean; diff --git a/src/vs/workbench/parts/debug/electron-browser/debugService.ts b/src/vs/workbench/parts/debug/electron-browser/debugService.ts index 6cd2475767e..f3ac026967d 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugService.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugService.ts @@ -564,11 +564,16 @@ export class DebugService implements debug.IDebugService { this.model.setExceptionBreakpoints(this.session.configuration.capabilities.exceptionBreakpointFilters); return configuration.request === 'attach' ? this.session.attach(configuration) : this.session.launch(configuration); }).then((result: DebugProtocol.Response) => { - if (changeViewState && !this.viewModel.changedWorkbenchViewState) { - // We only want to change the workbench view state on the first debug session #5738 - this.viewModel.changedWorkbenchViewState = true; - this.viewletService.openViewlet(debug.VIEWLET_ID); - this.panelService.openPanel(debug.REPL_ID, false).done(undefined, errors.onUnexpectedError); + if (changeViewState) { + if (configuration.internalConsoleOptions === 'openOnSessionStart' || (!this.viewModel.changedWorkbenchViewState && configuration.internalConsoleOptions === 'openOnFirstSessionStart')) { + this.panelService.openPanel(debug.REPL_ID, false).done(undefined, errors.onUnexpectedError); + } + + if (!this.viewModel.changedWorkbenchViewState) { + // We only want to change the workbench view state on the first debug session #5738 + this.viewModel.changedWorkbenchViewState = true; + this.viewletService.openViewlet(debug.VIEWLET_ID); + } } // Do not change status bar to orange if we are just running without debug. diff --git a/src/vs/workbench/parts/debug/node/debugAdapter.ts b/src/vs/workbench/parts/debug/node/debugAdapter.ts index b2dadceb57b..66f4bb2d739 100644 --- a/src/vs/workbench/parts/debug/node/debugAdapter.ts +++ b/src/vs/workbench/parts/debug/node/debugAdapter.ts @@ -106,6 +106,11 @@ export class Adapter { default: null, description: nls.localize('debugPrelaunchTask', "Task to run before debug session starts.") }; + properties.internalConsoleOptions = { + enum: ['neverOpen', 'openOnSessionStart', 'openOnFirstSessionStart'], + default: 'openOnFirstSessionStart', + description: nls.localize('internalConsoleOptions', "Controls behavior of the internal debug console.") + }; this.warnRelativePaths(properties.outDir); this.warnRelativePaths(properties.program); this.warnRelativePaths(properties.cwd); From 0e653f3168af56d1434b798b2c85c9140dd1ab93 Mon Sep 17 00:00:00 2001 From: isidor Date: Wed, 4 May 2016 12:58:07 +0200 Subject: [PATCH 047/297] debug: openOnFirstSessionStart is default value for internalConsoleOptions --- src/vs/workbench/parts/debug/electron-browser/debugService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/parts/debug/electron-browser/debugService.ts b/src/vs/workbench/parts/debug/electron-browser/debugService.ts index f3ac026967d..371d7e41c18 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugService.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugService.ts @@ -565,7 +565,7 @@ export class DebugService implements debug.IDebugService { return configuration.request === 'attach' ? this.session.attach(configuration) : this.session.launch(configuration); }).then((result: DebugProtocol.Response) => { if (changeViewState) { - if (configuration.internalConsoleOptions === 'openOnSessionStart' || (!this.viewModel.changedWorkbenchViewState && configuration.internalConsoleOptions === 'openOnFirstSessionStart')) { + if (configuration.internalConsoleOptions === 'openOnSessionStart' || (!this.viewModel.changedWorkbenchViewState && configuration.internalConsoleOptions !== 'neverOpen')) { this.panelService.openPanel(debug.REPL_ID, false).done(undefined, errors.onUnexpectedError); } From a9808d5f4f1fa1ab46e13c1131f85cba94ae0ad1 Mon Sep 17 00:00:00 2001 From: Andre Weinand Date: Wed, 4 May 2016 15:18:23 +0200 Subject: [PATCH 048/297] upgrade to debug protocol 1.8.0 --- extensions/node-debug/node-debug.azure.json | 2 +- npm-shrinkwrap.json | 6 +++--- package.json | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/extensions/node-debug/node-debug.azure.json b/extensions/node-debug/node-debug.azure.json index 37e8154a0ec..82b4ca4fa36 100644 --- a/extensions/node-debug/node-debug.azure.json +++ b/extensions/node-debug/node-debug.azure.json @@ -1,6 +1,6 @@ { "account": "monacobuild", "container": "debuggers", - "zip": "c2c41f3/node-debug.zip", + "zip": "4effb16/node-debug.zip", "output": "" } diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 2e50b73ddde..73aeae4a6eb 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -396,9 +396,9 @@ "resolved": "https://registry.npmjs.org/typechecker/-/typechecker-2.0.8.tgz" }, "vscode-debugprotocol": { - "version": "1.8.0-pre.3", - "from": "vscode-debugprotocol@1.8.0-pre.3", - "resolved": "https://registry.npmjs.org/vscode-debugprotocol/-/vscode-debugprotocol-1.8.0-pre.3.tgz" + "version": "1.8.0", + "from": "vscode-debugprotocol@1.8.0", + "resolved": "https://registry.npmjs.org/vscode-debugprotocol/-/vscode-debugprotocol-1.8.0.tgz" }, "vscode-textmate": { "version": "1.0.11", diff --git a/package.json b/package.json index d3457292405..4066a293192 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "native-keymap": "0.1.2", "sax": "1.1.2", "semver": "4.3.6", - "vscode-debugprotocol": "1.8.0-pre.3", + "vscode-debugprotocol": "1.8.0", "vscode-textmate": "1.0.11", "winreg": "1.2.0", "yauzl": "2.3.1" From 46b569c4579ca2eb2f866b3a3a5ea8f33fd643a0 Mon Sep 17 00:00:00 2001 From: isidor Date: Wed, 4 May 2016 16:08:50 +0200 Subject: [PATCH 049/297] debug: log adapter errors to 'extensions' output channel fixes #5832 --- .../debug/electron-browser/debugService.ts | 3 +-- .../parts/debug/node/rawDebugSession.ts | 18 +++++++++++------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/vs/workbench/parts/debug/electron-browser/debugService.ts b/src/vs/workbench/parts/debug/electron-browser/debugService.ts index 371d7e41c18..5293f0c9403 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugService.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugService.ts @@ -547,8 +547,7 @@ export class DebugService implements debug.IDebugService { telemetryInfo['common.vscodesessionid'] = info.sessionId; }, errors.onUnexpectedError); this.telemetryAdapter = new AIAdapter(key, this.configurationManager.adapter.type, null, telemetryInfo); - this.session = new session.RawDebugSession(this.messageService, this.telemetryService, configuration.debugServer, this.configurationManager.adapter, this.telemetryAdapter); - + this.session = this.instantiationService.createInstance(session.RawDebugSession, configuration.debugServer, this.configurationManager.adapter, this.telemetryAdapter); this.registerSessionListeners(); return this.session.initialize({ diff --git a/src/vs/workbench/parts/debug/node/rawDebugSession.ts b/src/vs/workbench/parts/debug/node/rawDebugSession.ts index 11110ab464f..7fd9d3d8ef0 100644 --- a/src/vs/workbench/parts/debug/node/rawDebugSession.ts +++ b/src/vs/workbench/parts/debug/node/rawDebugSession.ts @@ -14,12 +14,15 @@ import errors = require('vs/base/common/errors'); import { TPromise } from 'vs/base/common/winjs.base'; import severity from 'vs/base/common/severity'; import { AIAdapter } from 'vs/base/node/aiAdapter'; -import debug = require('vs/workbench/parts/debug/common/debug'); -import { Adapter } from 'vs/workbench/parts/debug/node/debugAdapter'; -import v8 = require('vs/workbench/parts/debug/node/v8Protocol'); import stdfork = require('vs/base/node/stdFork'); import { IMessageService, CloseAction } from 'vs/platform/message/common/message'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; +import debug = require('vs/workbench/parts/debug/common/debug'); +import { Adapter } from 'vs/workbench/parts/debug/node/debugAdapter'; +import v8 = require('vs/workbench/parts/debug/node/v8Protocol'); +import { IOutputService } from 'vs/workbench/parts/output/common/output'; +import { ExtensionsChannelId } from 'vs/workbench/parts/extensions/common/extensions'; + import { shell } from 'electron'; export interface SessionExitedEvent extends DebugProtocol.ExitedEvent { @@ -61,11 +64,12 @@ export class RawDebugSession extends v8.V8Protocol implements debug.IRawDebugSes private _onDidEvent: Emitter; constructor( - private messageService: IMessageService, - private telemetryService: ITelemetryService, private debugServerPort: number, private adapter: Adapter, - private telemtryAdapter: AIAdapter + private telemtryAdapter: AIAdapter, + @IMessageService private messageService: IMessageService, + @ITelemetryService private telemetryService: ITelemetryService, + @IOutputService private outputService: IOutputService ) { super(); this.emittedStopped = false; @@ -327,7 +331,7 @@ export class RawDebugSession extends v8.V8Protocol implements debug.IRawDebugSes // console.log('%c' + sanitize(data), 'background: #ddd; font-style: italic;'); // }); this.serverProcess.stderr.on('data', (data: string) => { - console.log(sanitize(data)); + this.outputService.getChannel(ExtensionsChannelId).append(sanitize(data)); }); this.connect(this.serverProcess.stdout, this.serverProcess.stdin); From ef9ebb5214fd008b176d734c526925eeb375c68f Mon Sep 17 00:00:00 2001 From: isidor Date: Wed, 4 May 2016 16:28:08 +0200 Subject: [PATCH 050/297] debug: open repl if some error got logged there on start fixes #5870 --- src/vs/workbench/parts/debug/electron-browser/debugService.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/vs/workbench/parts/debug/electron-browser/debugService.ts b/src/vs/workbench/parts/debug/electron-browser/debugService.ts index 5293f0c9403..3d1717e359d 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugService.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugService.ts @@ -593,6 +593,10 @@ export class DebugService implements debug.IDebugService { if (this.session) { this.session.disconnect(); } + // Show the repl if some error got logged there #5870 + if (this.model.getReplElements().length > 0) { + this.panelService.openPanel(debug.REPL_ID, false).done(undefined, errors.onUnexpectedError); + } const configureAction = this.instantiationService.createInstance(debugactions.ConfigureAction, debugactions.ConfigureAction.ID, debugactions.ConfigureAction.LABEL); const actions = (error.actions && error.actions.length) ? error.actions.concat([configureAction]) : [CloseAction, configureAction]; From b372166770ecd83113cd8d8f25d4a7faa853aed0 Mon Sep 17 00:00:00 2001 From: isidor Date: Wed, 4 May 2016 16:47:46 +0200 Subject: [PATCH 051/297] debug: different max value render lengths for repl / hover / viewlet fixes #5823 --- .../parts/debug/browser/debugHover.ts | 3 +- .../parts/debug/browser/debugViewer.ts | 80 +++++++++---------- 2 files changed, 42 insertions(+), 41 deletions(-) diff --git a/src/vs/workbench/parts/debug/browser/debugHover.ts b/src/vs/workbench/parts/debug/browser/debugHover.ts index 3d41a55df1a..345b37712f7 100644 --- a/src/vs/workbench/parts/debug/browser/debugHover.ts +++ b/src/vs/workbench/parts/debug/browser/debugHover.ts @@ -27,6 +27,7 @@ const debugTreeOptions = { ariaLabel: nls.localize('treeAriaLabel', "Debug Hover") }; const MAX_ELEMENTS_SHOWN = 18; +const MAX_VALUE_RENDER_LENGTH_IN_HOVER = 4096; export class DebugHoverWidget implements editorbrowser.IContentWidget { @@ -182,7 +183,7 @@ export class DebugHoverWidget implements editorbrowser.IContentWidget { if (expression.reference === 0 || forceValueHover) { this.treeContainer.hidden = true; this.valueContainer.hidden = false; - viewer.renderExpressionValue(expression, this.valueContainer, false); + viewer.renderExpressionValue(expression, this.valueContainer, false, MAX_VALUE_RENDER_LENGTH_IN_HOVER); this.valueContainer.title = ''; this.editor.layoutContentWidget(this); if (focus) { diff --git a/src/vs/workbench/parts/debug/browser/debugViewer.ts b/src/vs/workbench/parts/debug/browser/debugViewer.ts index 48833ac4838..0561bcd2b3b 100644 --- a/src/vs/workbench/parts/debug/browser/debugViewer.ts +++ b/src/vs/workbench/parts/debug/browser/debugViewer.ts @@ -35,9 +35,9 @@ import {IKeyboardEvent} from 'vs/base/browser/keyboardEvent'; const $ = dom.emmet; const booleanRegex = /^true|false$/i; const stringRegex = /^(['"]).*\1$/; -const MAX_VALUE_RENDER_LENGTH = 5000; +const MAX_VALUE_RENDER_LENGTH_IN_VIEWLET = 1024; -export function renderExpressionValue(expressionOrValue: debug.IExpression|string, container: HTMLElement, showChanged: boolean): void { +export function renderExpressionValue(expressionOrValue: debug.IExpression | string, container: HTMLElement, showChanged: boolean, maxValueRenderLength?: number): void { let value = typeof expressionOrValue === 'string' ? expressionOrValue : expressionOrValue.value; // remove stale classes @@ -61,8 +61,8 @@ export function renderExpressionValue(expressionOrValue: debug.IExpression|strin container.className = 'value changed'; } - if (value.length > MAX_VALUE_RENDER_LENGTH) { - value = value.substr(0, MAX_VALUE_RENDER_LENGTH) + '...'; + if (maxValueRenderLength && value.length > maxValueRenderLength) { + value = value.substr(0, maxValueRenderLength) + '...'; } container.textContent = value; container.title = value; @@ -74,7 +74,7 @@ export function renderVariable(tree: tree.ITree, variable: model.Variable, data: } if (variable.value) { - renderExpressionValue(variable, data.value, showChanged); + renderExpressionValue(variable, data.value, showChanged, MAX_VALUE_RENDER_LENGTH_IN_VIEWLET); data.expression.title = variable.value; } else { data.value.textContent = ''; @@ -195,7 +195,7 @@ export class BaseDebugController extends treedefaults.DefaultController { export class CallStackActionProvider implements renderer.IActionProvider { - constructor(@IInstantiationService private instantiationService: IInstantiationService) { + constructor( @IInstantiationService private instantiationService: IInstantiationService) { // noop } @@ -233,7 +233,7 @@ export class CallStackActionProvider implements renderer.IActionProvider { export class CallStackDataSource implements tree.IDataSource { - constructor(@debug.IDebugService private debugService: debug.IDebugService) { + constructor( @debug.IDebugService private debugService: debug.IDebugService) { // noop } @@ -286,10 +286,10 @@ interface ILoadMoreTemplateData { interface IStackFrameTemplateData { stackFrame: HTMLElement; - label : HTMLElement; - file : HTMLElement; - fileName : HTMLElement; - lineNumber : HTMLElement; + label: HTMLElement; + file: HTMLElement; + fileName: HTMLElement; + lineNumber: HTMLElement; } export class CallStackRenderer implements tree.IRenderer { @@ -298,11 +298,11 @@ export class CallStackRenderer implements tree.IRenderer { private static STACK_FRAME_TEMPLATE_ID = 'stackFrame'; private static LOAD_MORE_TEMPLATE_ID = 'loadMore'; - constructor(@IWorkspaceContextService private contextService: IWorkspaceContextService) { + constructor( @IWorkspaceContextService private contextService: IWorkspaceContextService) { // noop } - public getHeight(tree:tree.ITree, element:any): number { + public getHeight(tree: tree.ITree, element: any): number { return 22; } @@ -371,7 +371,7 @@ export class CallStackRenderer implements tree.IRenderer { data.label.title = stackFrame.name; data.fileName.textContent = getSourceName(stackFrame.source, this.contextService); if (stackFrame.source.available && stackFrame.lineNumber !== undefined) { - data.lineNumber.textContent = `${ stackFrame.lineNumber }`; + data.lineNumber.textContent = `${stackFrame.lineNumber}`; dom.removeClass(data.lineNumber, 'unavailable'); } else { dom.addClass(data.lineNumber, 'unavailable'); @@ -385,7 +385,7 @@ export class CallStackRenderer implements tree.IRenderer { export class CallstackAccessibilityProvider implements tree.IAccessibilityProvider { - constructor(@IWorkspaceContextService private contextService: IWorkspaceContextService) { + constructor( @IWorkspaceContextService private contextService: IWorkspaceContextService) { // noop } @@ -423,7 +423,7 @@ export class VariablesActionProvider implements renderer.IActionProvider { public getSecondaryActions(tree: tree.ITree, element: any): TPromise { let actions: actions.Action[] = []; - const variable = element; + const variable = element; actions.push(this.instantiationService.createInstance(debugactions.AddToWatchExpressionsAction, debugactions.AddToWatchExpressionsAction.ID, debugactions.AddToWatchExpressionsAction.LABEL, variable)); if (variable.reference === 0) { actions.push(this.instantiationService.createInstance(debugactions.CopyValueAction, debugactions.CopyValueAction.ID, debugactions.CopyValueAction.LABEL, variable)); @@ -452,17 +452,17 @@ export class VariablesDataSource implements tree.IDataSource { return true; } - let variable = element; + let variable = element; return variable.reference !== 0 && !strings.equalsIgnoreCase(variable.value, 'null'); } public getChildren(tree: tree.ITree, element: any): TPromise { if (element instanceof viewmodel.ViewModel) { - let focusedStackFrame = ( element).getFocusedStackFrame(); + let focusedStackFrame = (element).getFocusedStackFrame(); return focusedStackFrame ? focusedStackFrame.getScopes(this.debugService) : TPromise.as([]); } - let scope = element; + let scope = element; return scope.getChildren(this.debugService); } @@ -577,7 +577,7 @@ export class WatchExpressionsActionProvider implements renderer.IActionProvider public getSecondaryActions(tree: tree.ITree, element: any): TPromise { const actions: actions.Action[] = []; if (element instanceof model.Expression) { - const expression = element; + const expression = element; actions.push(this.instantiationService.createInstance(debugactions.AddWatchExpressionAction, debugactions.AddWatchExpressionAction.ID, debugactions.AddWatchExpressionAction.LABEL)); actions.push(this.instantiationService.createInstance(debugactions.RenameWatchExpressionAction, debugactions.RenameWatchExpressionAction.ID, debugactions.RenameWatchExpressionAction.LABEL, expression)); if (expression.reference === 0) { @@ -590,7 +590,7 @@ export class WatchExpressionsActionProvider implements renderer.IActionProvider } else { actions.push(this.instantiationService.createInstance(debugactions.AddWatchExpressionAction, debugactions.AddWatchExpressionAction.ID, debugactions.AddWatchExpressionAction.LABEL)); if (element instanceof model.Variable) { - const variable = element; + const variable = element; if (variable.reference === 0) { actions.push(this.instantiationService.createInstance(debugactions.CopyValueAction, debugactions.CopyValueAction.ID, debugactions.CopyValueAction.LABEL, variable.value)); } @@ -622,16 +622,16 @@ export class WatchExpressionsDataSource implements tree.IDataSource { return true; } - const watchExpression = element; + const watchExpression = element; return watchExpression.reference !== 0 && !strings.equalsIgnoreCase(watchExpression.value, 'null'); } public getChildren(tree: tree.ITree, element: any): TPromise { if (element instanceof model.Model) { - return TPromise.as(( element).getWatchExpressions()); + return TPromise.as((element).getWatchExpressions()); } - let expression = element; + let expression = element; return expression.getChildren(this.debugService); } @@ -657,10 +657,10 @@ export class WatchExpressionsRenderer implements tree.IRenderer { @IContextViewService private contextViewService: IContextViewService ) { this.toDispose = []; - this.actionProvider = actionProvider; + this.actionProvider = actionProvider; } - public getHeight(tree:tree.ITree, element:any): number { + public getHeight(tree: tree.ITree, element: any): number { return 22; } @@ -676,7 +676,7 @@ export class WatchExpressionsRenderer implements tree.IRenderer { let data: IWatchExpressionTemplateData = Object.create(null); if (templateId === WatchExpressionsRenderer.WATCH_EXPRESSION_TEMPLATE_ID) { data.actionBar = new actionbar.ActionBar(container, { actionRunner: this.actionRunner }); - data.actionBar.push(this.actionProvider.getExpressionActions() , { icon: true, label: false }); + data.actionBar.push(this.actionProvider.getExpressionActions(), { icon: true, label: false }); } data.expression = dom.append(container, $(isMacintosh ? '.expression.mac' : '.expression.win-linux')); @@ -703,7 +703,7 @@ export class WatchExpressionsRenderer implements tree.IRenderer { data.name.textContent = `${watchExpression.name}:`; if (watchExpression.value) { - renderExpressionValue(watchExpression, data.value, true); + renderExpressionValue(watchExpression, data.value, true, MAX_VALUE_RENDER_LENGTH_IN_VIEWLET); data.expression.title = watchExpression.value; } } @@ -748,7 +748,7 @@ export class WatchExpressionsController extends BaseDebugController { protected onLeftClick(tree: tree.ITree, element: any, event: mouse.IMouseEvent): boolean { // double click on primitive value: open input box to be able to select and copy value. if (element instanceof model.Expression && event.detail === 2) { - const expression = element; + const expression = element; if (expression.reference === 0) { this.debugService.getViewModel().setSelectedExpression(expression); } @@ -761,7 +761,7 @@ export class WatchExpressionsController extends BaseDebugController { protected onRename(tree: tree.ITree, event: KeyboardEvent): boolean { const element = tree.getFocus(); if (element instanceof model.Expression) { - const watchExpression = element; + const watchExpression = element; if (watchExpression.reference === 0) { this.debugService.getViewModel().setSelectedExpression(watchExpression); } @@ -774,7 +774,7 @@ export class WatchExpressionsController extends BaseDebugController { protected onDelete(tree: tree.ITree, event: IKeyboardEvent): boolean { const element = tree.getFocus(); if (element instanceof model.Expression) { - const we = element; + const we = element; this.debugService.removeWatchExpressions(we.getId()); return true; @@ -856,8 +856,8 @@ export class BreakpointsDataSource implements tree.IDataSource { } public getChildren(tree: tree.ITree, element: any): TPromise { - const model = element; - const exBreakpoints = model.getExceptionBreakpoints(); + const model = element; + const exBreakpoints = model.getExceptionBreakpoints(); return TPromise.as(exBreakpoints.concat(model.getFunctionBreakpoints()).concat(model.getBreakpoints())); } @@ -901,7 +901,7 @@ export class BreakpointsRenderer implements tree.IRenderer { // noop } - public getHeight(tree:tree.ITree, element:any): number { + public getHeight(tree: tree.ITree, element: any): number { return 22; } @@ -929,7 +929,7 @@ export class BreakpointsRenderer implements tree.IRenderer { data.breakpoint = dom.append(container, $('.breakpoint')); data.toDisposeBeforeRender = []; - data.checkbox = $('input'); + data.checkbox = $('input'); data.checkbox.type = 'checkbox'; if (!isMacintosh) { data.checkbox.className = 'checkbox-win-linux'; @@ -963,7 +963,7 @@ export class BreakpointsRenderer implements tree.IRenderer { } private renderExceptionBreakpoint(exceptionBreakpoint: debug.IExceptionBreakpoint, data: IExceptionBreakpointTemplateData): void { - data.name.textContent = exceptionBreakpoint.label || `${ exceptionBreakpoint.filter } exceptions`;; + data.name.textContent = exceptionBreakpoint.label || `${exceptionBreakpoint.filter} exceptions`;; data.checkbox.checked = exceptionBreakpoint.enabled; } @@ -1008,7 +1008,7 @@ export class BreakpointsRenderer implements tree.IRenderer { export class BreakpointsAccessibilityProvider implements tree.IAccessibilityProvider { - constructor(@IWorkspaceContextService private contextService: IWorkspaceContextService) { + constructor( @IWorkspaceContextService private contextService: IWorkspaceContextService) { // noop } @@ -1029,7 +1029,7 @@ export class BreakpointsAccessibilityProvider implements tree.IAccessibilityProv export class BreakpointsController extends BaseDebugController { - protected onLeftClick(tree:tree.ITree, element: any, event: mouse.IMouseEvent): boolean { + protected onLeftClick(tree: tree.ITree, element: any, event: mouse.IMouseEvent): boolean { if (element instanceof model.FunctionBreakpoint && event.detail === 2) { this.debugService.getViewModel().setSelectedFunctionBreakpoint(element); return true; @@ -1050,10 +1050,10 @@ export class BreakpointsController extends BaseDebugController { protected onDelete(tree: tree.ITree, event: IKeyboardEvent): boolean { const element = tree.getFocus(); if (element instanceof model.Breakpoint) { - this.debugService.removeBreakpoints(( element).getId()).done(null, errors.onUnexpectedError); + this.debugService.removeBreakpoints((element).getId()).done(null, errors.onUnexpectedError); return true; } else if (element instanceof model.FunctionBreakpoint) { - const fbp = element; + const fbp = element; this.debugService.removeFunctionBreakpoints(fbp.getId()).done(null, errors.onUnexpectedError); return true; From 81050abedbe54597b9506609eb5b7cb916ddc9c6 Mon Sep 17 00:00:00 2001 From: isidor Date: Wed, 4 May 2016 16:51:06 +0200 Subject: [PATCH 052/297] debug: format polish --- .../parts/debug/browser/breakpointWidget.ts | 2 +- .../parts/debug/browser/debugActionItems.ts | 2 +- .../debug/browser/debugEditorContribution.ts | 4 +- .../parts/debug/browser/replViewer.ts | 6 +- src/vs/workbench/parts/debug/common/debug.ts | 4 +- .../electron-browser/debug.contribution.ts | 4 +- .../debug/electron-browser/debugService.ts | 113 +++++++++--------- .../workbench/parts/debug/node/v8Protocol.ts | 2 +- 8 files changed, 70 insertions(+), 67 deletions(-) diff --git a/src/vs/workbench/parts/debug/browser/breakpointWidget.ts b/src/vs/workbench/parts/debug/browser/breakpointWidget.ts index d54b89463ca..d3f865be6d6 100644 --- a/src/vs/workbench/parts/debug/browser/breakpointWidget.ts +++ b/src/vs/workbench/parts/debug/browser/breakpointWidget.ts @@ -120,7 +120,7 @@ export class BreakpointWidget extends ZoneWidget { } } -CommonEditorRegistry.registerEditorCommand(CLOSE_BREAKPOINT_WIDGET_COMMAND_ID, CommonEditorRegistry.commandWeight(8), { primary: KeyCode.Escape, secondary: [KeyMod.Shift | KeyCode.Escape] }, false, CONTEXT_BREAKPOINT_WIDGET_VISIBLE, (ctx, editor, args) => { +CommonEditorRegistry.registerEditorCommand(CLOSE_BREAKPOINT_WIDGET_COMMAND_ID, CommonEditorRegistry.commandWeight(8), { primary: KeyCode.Escape, secondary: [KeyMod.Shift | KeyCode.Escape] }, false, CONTEXT_BREAKPOINT_WIDGET_VISIBLE, (ctx, editor, args) => { if (BreakpointWidget.INSTANCE) { BreakpointWidget.INSTANCE.dispose(); } diff --git a/src/vs/workbench/parts/debug/browser/debugActionItems.ts b/src/vs/workbench/parts/debug/browser/debugActionItems.ts index 46b396ae6c4..5ff87faed7e 100644 --- a/src/vs/workbench/parts/debug/browser/debugActionItems.ts +++ b/src/vs/workbench/parts/debug/browser/debugActionItems.ts @@ -39,7 +39,7 @@ export class SelectConfigActionItem extends BaseActionItem { this.toDispose.push(this.debugService.onDidChangeState(state => { this.select.disabled = state !== State.Inactive; })); - this.toDispose.push(configurationService.onDidUpdateConfiguration(e => { + this.toDispose.push(configurationService.onDidUpdateConfiguration(e => { this.setOptions().done(null, errors.onUnexpectedError); })); } diff --git a/src/vs/workbench/parts/debug/browser/debugEditorContribution.ts b/src/vs/workbench/parts/debug/browser/debugEditorContribution.ts index 184a9a70bb2..10d2850ee92 100644 --- a/src/vs/workbench/parts/debug/browser/debugEditorContribution.ts +++ b/src/vs/workbench/parts/debug/browser/debugEditorContribution.ts @@ -42,7 +42,7 @@ export class DebugEditorContribution implements debug.IDebugEditorContribution { @debug.IDebugService private debugService: debug.IDebugService, @IWorkspaceContextService private contextService: IWorkspaceContextService, @IContextMenuService private contextMenuService: IContextMenuService, - @IInstantiationService private instantiationService:IInstantiationService + @IInstantiationService private instantiationService: IInstantiationService ) { this.breakpointHintDecoration = []; this.hoverWidget = new DebugHoverWidget(this.editor, this.debugService, this.instantiationService); @@ -64,7 +64,7 @@ export class DebugEditorContribution implements debug.IDebugEditorContribution { nls.localize('addBreakpoint', "Add Breakpoint"), null, true, - () => this.debugService.addBreakpoints([{ uri, lineNumber }]) + () => this.debugService.addBreakpoints([{ uri, lineNumber }]) )); actions.push(this.instantiationService.createInstance(debugactions.AddConditionalBreakpointAction, debugactions.AddConditionalBreakpointAction.ID, debugactions.AddConditionalBreakpointAction.LABEL, this.editor, lineNumber)); } diff --git a/src/vs/workbench/parts/debug/browser/replViewer.ts b/src/vs/workbench/parts/debug/browser/replViewer.ts index ca6355a5335..34a488b10a5 100644 --- a/src/vs/workbench/parts/debug/browser/replViewer.ts +++ b/src/vs/workbench/parts/debug/browser/replViewer.ts @@ -44,7 +44,7 @@ export class ReplExpressionsDataSource implements tree.IDataSource { } public hasChildren(tree: tree.ITree, element: any): boolean { - return element instanceof model.Model || element.reference > 0 || (element instanceof model.KeyValueOutputElement && element.getChildren().length > 0); + return element instanceof model.Model || element.reference > 0 || (element instanceof model.KeyValueOutputElement && element.getChildren().length > 0); } public getChildren(tree: tree.ITree, element: any): TPromise { @@ -58,7 +58,7 @@ export class ReplExpressionsDataSource implements tree.IDataSource { return TPromise.as(null); } - return ( element).getChildren(this.debugService); + return (element).getChildren(this.debugService); } public getParent(tree: tree.ITree, element: any): TPromise { @@ -490,7 +490,7 @@ export class ReplExpressionsController extends debugviewer.BaseDebugController { } protected onLeftClick(tree: tree.ITree, element: any, eventish: treedefaults.ICancelableEvent, origin: string = 'mouse'): boolean { - const mouseEvent = eventish; + const mouseEvent = eventish; // input and output are one element in the tree => we only expand if the user clicked on the output. if ((element.reference > 0 || (element instanceof model.KeyValueOutputElement && element.getChildren().length > 0)) && mouseEvent.target.className.indexOf('input expression') === -1) { super.onLeftClick(tree, element, eventish, origin); diff --git a/src/vs/workbench/parts/debug/common/debug.ts b/src/vs/workbench/parts/debug/common/debug.ts index f0846b866cb..aba1e3081bf 100644 --- a/src/vs/workbench/parts/debug/common/debug.ts +++ b/src/vs/workbench/parts/debug/common/debug.ts @@ -444,8 +444,8 @@ export var DebugViewRegistry = new DebugViewRegistryImpl(); const _formatPIIRegexp = /{([^}]+)}/g; -export function formatPII(value:string, excludePII: boolean, args: {[key: string]: string}): string { - return value.replace(_formatPIIRegexp, function(match, group) { +export function formatPII(value: string, excludePII: boolean, args: { [key: string]: string }): string { + return value.replace(_formatPIIRegexp, function (match, group) { if (excludePII && group.length > 0 && group[0] !== '_') { return match; } diff --git a/src/vs/workbench/parts/debug/electron-browser/debug.contribution.ts b/src/vs/workbench/parts/debug/electron-browser/debug.contribution.ts index 4a63438210e..83889ef0cd7 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debug.contribution.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debug.contribution.ts @@ -91,7 +91,7 @@ debug.DebugViewRegistry.registerDebugView(CallStackView, 30); debug.DebugViewRegistry.registerDebugView(BreakpointsView, 40); // register action to open viewlet -const registry = ( platform.Registry.as(wbaregistry.Extensions.WorkbenchActions)); +const registry = (platform.Registry.as(wbaregistry.Extensions.WorkbenchActions)); registry.registerWorkbenchAction(new SyncActionDescriptor(OpenDebugViewletAction, OpenDebugViewletAction.ID, OpenDebugViewletAction.LABEL, openViewletKb), 'View: Show Debug', nls.localize('view', "View")); (platform.Registry.as(wbext.Extensions.Workbench)).registerWorkbenchContribution(DebugEditorModelManager); @@ -108,7 +108,7 @@ registry.registerWorkbenchAction(new SyncActionDescriptor(dbgactions.StopDebugAc registry.registerWorkbenchAction(new SyncActionDescriptor(dbgactions.ContinueAction, dbgactions.ContinueAction.ID, dbgactions.ContinueAction.LABEL, { primary: KeyCode.F5 }, KbExpr.has(debug.CONTEXT_IN_DEBUG_MODE)), 'Debug: Continue', debugCategory); registry.registerWorkbenchAction(new SyncActionDescriptor(dbgactions.PauseAction, dbgactions.PauseAction.ID, dbgactions.PauseAction.LABEL), 'Debug: Pause', debugCategory); registry.registerWorkbenchAction(new SyncActionDescriptor(dbgactions.ConfigureAction, dbgactions.ConfigureAction.ID, dbgactions.ConfigureAction.LABEL), 'Debug: Open launch.json', debugCategory); -registry.registerWorkbenchAction(new SyncActionDescriptor(dbgactions.ToggleReplAction, dbgactions.ToggleReplAction.ID, dbgactions.ToggleReplAction.LABEL, { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_Y,}), 'Debug: Debug Console', debugCategory); +registry.registerWorkbenchAction(new SyncActionDescriptor(dbgactions.ToggleReplAction, dbgactions.ToggleReplAction.ID, dbgactions.ToggleReplAction.LABEL, { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_Y, }), 'Debug: Debug Console', debugCategory); registry.registerWorkbenchAction(new SyncActionDescriptor(dbgactions.AddFunctionBreakpointAction, dbgactions.AddFunctionBreakpointAction.ID, dbgactions.AddFunctionBreakpointAction.LABEL), 'Debug: Add Function Breakpoint', debugCategory); registry.registerWorkbenchAction(new SyncActionDescriptor(dbgactions.ReapplyBreakpointsAction, dbgactions.ReapplyBreakpointsAction.ID, dbgactions.ReapplyBreakpointsAction.LABEL), 'Debug: Reapply All Breakpoints', debugCategory); registry.registerWorkbenchAction(new SyncActionDescriptor(dbgactions.RunAction, dbgactions.RunAction.ID, dbgactions.RunAction.LABEL, { primary: KeyMod.CtrlCmd | KeyCode.F5 }, KbExpr.not(debug.CONTEXT_IN_DEBUG_MODE)), 'Debug: Start Without Debugging', debugCategory); diff --git a/src/vs/workbench/parts/debug/electron-browser/debugService.ts b/src/vs/workbench/parts/debug/electron-browser/debugService.ts index 3d1717e359d..fb3927b1758 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugService.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugService.ts @@ -88,7 +88,7 @@ export class DebugService implements debug.IDebugService { @IKeybindingService keybindingService: IKeybindingService, @IEventService eventService: IEventService, @ILifecycleService private lifecycleService: ILifecycleService, - @IInstantiationService private instantiationService:IInstantiationService, + @IInstantiationService private instantiationService: IInstantiationService, @IExtensionService private extensionService: IExtensionService, @IMarkerService private markerService: IMarkerService, @ITaskService private taskService: ITaskService, @@ -403,11 +403,11 @@ export class DebugService implements debug.IDebugService { } } - public enableOrDisableBreakpoints(enable: boolean, breakpoint?: debug.IEnablement): TPromise{ + public enableOrDisableBreakpoints(enable: boolean, breakpoint?: debug.IEnablement): TPromise { if (breakpoint) { this.model.setEnablement(breakpoint, enable); if (breakpoint instanceof model.Breakpoint) { - return this.sendBreakpoints(( breakpoint).source.uri); + return this.sendBreakpoints((breakpoint).source.uri); } else if (breakpoint instanceof model.FunctionBreakpoint) { return this.sendFunctionBreakpoints(); } @@ -489,53 +489,53 @@ export class DebugService implements debug.IDebugService { this.removeReplExpressions(); return this.textFileService.saveAll() // make sure all dirty files are saved - .then(() => this.configurationService.loadConfiguration() // make sure configuration is up to date - .then(() => this.extensionService.onReady() - .then(() => this.configurationManager.setConfiguration((this.configurationManager.configurationName)) - .then(() => { - const configuration = this.configurationManager.configuration; - if (!configuration) { - return this.configurationManager.openConfigFile(false).then(openend => { - if (openend) { - this.messageService.show(severity.Info, nls.localize('NewLaunchConfig', "Please set up the launch configuration file for your application.")); - } - }); - } + .then(() => this.configurationService.loadConfiguration() // make sure configuration is up to date + .then(() => this.extensionService.onReady() + .then(() => this.configurationManager.setConfiguration((this.configurationManager.configurationName)) + .then(() => { + const configuration = this.configurationManager.configuration; + if (!configuration) { + return this.configurationManager.openConfigFile(false).then(openend => { + if (openend) { + this.messageService.show(severity.Info, nls.localize('NewLaunchConfig', "Please set up the launch configuration file for your application.")); + } + }); + } - configuration.noDebug = noDebug; - if (!this.configurationManager.adapter) { - return configuration.type ? TPromise.wrapError(new Error(nls.localize('debugTypeNotSupported', "Configured debug type '{0}' is not supported.", configuration.type))) - : TPromise.wrapError(errors.create(nls.localize('debugTypeMissing', "Missing property 'type' for the selected configuration in launch.json."), - { actions: [CloseAction, this.instantiationService.createInstance(debugactions.ConfigureAction, debugactions.ConfigureAction.ID, debugactions.ConfigureAction.LABEL)] })); - } + configuration.noDebug = noDebug; + if (!this.configurationManager.adapter) { + return configuration.type ? TPromise.wrapError(new Error(nls.localize('debugTypeNotSupported', "Configured debug type '{0}' is not supported.", configuration.type))) + : TPromise.wrapError(errors.create(nls.localize('debugTypeMissing', "Missing property 'type' for the selected configuration in launch.json."), + { actions: [CloseAction, this.instantiationService.createInstance(debugactions.ConfigureAction, debugactions.ConfigureAction.ID, debugactions.ConfigureAction.LABEL)] })); + } - return this.runPreLaunchTask(configuration.preLaunchTask).then((taskSummary: ITaskSummary) => { - const errorCount = configuration.preLaunchTask ? this.markerService.getStatistics().errors : 0; - const failureExitCode = taskSummary && taskSummary.exitCode !== undefined && taskSummary.exitCode !== 0; - if (errorCount === 0 && !failureExitCode) { - return this.doCreateSession(configuration, changeViewState); - } + return this.runPreLaunchTask(configuration.preLaunchTask).then((taskSummary: ITaskSummary) => { + const errorCount = configuration.preLaunchTask ? this.markerService.getStatistics().errors : 0; + const failureExitCode = taskSummary && taskSummary.exitCode !== undefined && taskSummary.exitCode !== 0; + if (errorCount === 0 && !failureExitCode) { + return this.doCreateSession(configuration, changeViewState); + } - this.messageService.show(severity.Error, { - message: errorCount > 1 ? nls.localize('preLaunchTaskErrors', "Build errors have been detected during preLaunchTask '{0}'.", configuration.preLaunchTask) : - errorCount === 1 ? nls.localize('preLaunchTaskError', "Build error has been detected during preLaunchTask '{0}'.", configuration.preLaunchTask) : - nls.localize('preLaunchTaskExitCode', "The preLaunchTask '{0}' terminated with exit code {1}.", configuration.preLaunchTask, taskSummary.exitCode), - actions: [CloseAction, new Action('debug.continue', nls.localize('debugAnyway', "Debug Anyway"), null, true, () => { - this.messageService.hideAll(); - return this.doCreateSession(configuration, changeViewState); - })] - }); - }, (err: TaskError) => { - if (err.code !== TaskErrors.NotConfigured) { - throw err; - } + this.messageService.show(severity.Error, { + message: errorCount > 1 ? nls.localize('preLaunchTaskErrors', "Build errors have been detected during preLaunchTask '{0}'.", configuration.preLaunchTask) : + errorCount === 1 ? nls.localize('preLaunchTaskError', "Build error has been detected during preLaunchTask '{0}'.", configuration.preLaunchTask) : + nls.localize('preLaunchTaskExitCode', "The preLaunchTask '{0}' terminated with exit code {1}.", configuration.preLaunchTask, taskSummary.exitCode), + actions: [CloseAction, new Action('debug.continue', nls.localize('debugAnyway', "Debug Anyway"), null, true, () => { + this.messageService.hideAll(); + return this.doCreateSession(configuration, changeViewState); + })] + }); + }, (err: TaskError) => { + if (err.code !== TaskErrors.NotConfigured) { + throw err; + } - this.messageService.show(err.severity, { - message: err.message, - actions: [CloseAction, this.taskService.configureAction()] - }); - }); - })))); + this.messageService.show(err.severity, { + message: err.message, + actions: [CloseAction, this.taskService.configureAction()] + }); + }); + })))); } private doCreateSession(configuration: debug.IConfig, changeViewState: boolean): TPromise { @@ -579,7 +579,7 @@ export class DebugService implements debug.IDebugService { if (!configuration.noDebug) { this.partService.addClass('debugging'); } - this.extensionService.activateByEvent(`onDebug:${ configuration.type }`).done(null, errors.onUnexpectedError); + this.extensionService.activateByEvent(`onDebug:${configuration.type}`).done(null, errors.onUnexpectedError); this.contextService.updateOptions('editor', { glyphMargin: true }); @@ -711,7 +711,7 @@ export class DebugService implements debug.IDebugService { // set breakpoints back to unverified since the session ended. // source reference changes across sessions, so we do not use it to persist the source. - const data: {[id: string]: { line: number, verified: boolean } } = { }; + const data: { [id: string]: { line: number, verified: boolean } } = {}; this.model.getBreakpoints().forEach(bp => { delete bp.source.raw.sourceReference; data[bp.getId()] = { line: bp.lineNumber, verified: false }; @@ -843,7 +843,7 @@ export class DebugService implements debug.IDebugService { return TPromise.as(null); } - return this.session.pause({ threadId } ); + return this.session.pause({ threadId }); } @@ -911,14 +911,17 @@ export class DebugService implements debug.IDebugService { const breakpointsToSend = arrays.distinct( this.model.getBreakpoints().filter(bp => this.model.areBreakpointsActivated() && bp.enabled && bp.source.uri.toString() === modelUri.toString()), - bp => `${ bp.desiredLineNumber }` + bp => `${bp.desiredLineNumber}` ); const rawSource = breakpointsToSend.length > 0 ? breakpointsToSend[0].source.raw : Source.toRawSource(modelUri, this.model); - return this.session.setBreakpoints({ source: rawSource, lines: breakpointsToSend.map(bp => bp.desiredLineNumber), - breakpoints: breakpointsToSend.map(bp => ({ line: bp.desiredLineNumber, condition: bp.condition })) }).then(response => { - - const data: {[id: string]: { line?: number, verified: boolean } } = { }; + return this.session.setBreakpoints({ + source: rawSource, + lines: breakpointsToSend.map(bp => bp.desiredLineNumber), + breakpoints: breakpointsToSend.map(bp => ({ line: bp.desiredLineNumber, + condition: bp.condition + }))}).then(response => { + const data: { [id: string]: { line?: number, verified: boolean } } = {}; for (let i = 0; i < breakpointsToSend.length; i++) { data[breakpointsToSend[i].getId()] = response.body.breakpoints[i]; } @@ -934,7 +937,7 @@ export class DebugService implements debug.IDebugService { const breakpointsToSend = this.model.getFunctionBreakpoints().filter(fbp => fbp.enabled && this.model.areBreakpointsActivated()); return this.session.setFunctionBreakpoints({ breakpoints: breakpointsToSend }).then(response => { - const data: {[id: string]: { name?: string, verified?: boolean } } = { }; + const data: { [id: string]: { name?: string, verified?: boolean } } = {}; for (let i = 0; i < breakpointsToSend.length; i++) { data[breakpointsToSend[i].getId()] = response.body.breakpoints[i]; } diff --git a/src/vs/workbench/parts/debug/node/v8Protocol.ts b/src/vs/workbench/parts/debug/node/v8Protocol.ts index ca471fdaea1..340ec55ef33 100644 --- a/src/vs/workbench/parts/debug/node/v8Protocol.ts +++ b/src/vs/workbench/parts/debug/node/v8Protocol.ts @@ -110,7 +110,7 @@ export abstract class V8Protocol { if (typeof rawData.event !== 'undefined') { this.onEvent(rawData); } else { - const response = rawData; + const response = rawData; const clb = this.pendingRequests[response.request_seq]; if (clb) { delete this.pendingRequests[response.request_seq]; From 64c185e5ae5a3143768d337437d167d5406af042 Mon Sep 17 00:00:00 2001 From: isidor Date: Wed, 4 May 2016 17:13:47 +0200 Subject: [PATCH 053/297] debug: auto expand complex expressions in repl fixes #6019 --- src/vs/workbench/parts/debug/browser/repl.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/parts/debug/browser/repl.ts b/src/vs/workbench/parts/debug/browser/repl.ts index 281eb11167c..5c860f6fb68 100644 --- a/src/vs/workbench/parts/debug/browser/repl.ts +++ b/src/vs/workbench/parts/debug/browser/repl.ts @@ -18,6 +18,7 @@ import { IEventService } from 'vs/platform/event/common/event'; import { EventType, CompositeEvent } from 'vs/workbench/common/events'; import viewer = require('vs/workbench/parts/debug/browser/replViewer'); import debug = require('vs/workbench/parts/debug/common/debug'); +import { Expression } from 'vs/workbench/parts/debug/common/debugModel'; import debugactions = require('vs/workbench/parts/debug/electron-browser/debugActions'); import replhistory = require('vs/workbench/parts/debug/common/replHistory'); import { Panel } from 'vs/workbench/browser/panel'; @@ -98,7 +99,14 @@ export class Repl extends Panel { const scrollPosition = this.tree.getScrollPosition(); this.tree.refresh().then(() => { if (scrollPosition === 0 || scrollPosition === 1) { - return this.tree.setScrollPosition(1); // keep scrolling to the end unless user scrolled up + this.tree.setScrollPosition(1); // keep scrolling to the end unless user scrolled up + } + + // If the last repl element has children - auto expand it #6019 + const elements = this.debugService.getModel().getReplElements(); + const lastElement = elements.length > 0 ? elements[elements.length - 1] : null; + if (lastElement instanceof Expression && lastElement.reference > 0) { + return this.tree.expand(elements[elements.length - 1]); } }, errors.onUnexpectedError); }, Repl.REFRESH_DELAY); From faf07be9e2c07d4dd5b8561e13d9f59f11460bb8 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Wed, 4 May 2016 15:08:48 +0200 Subject: [PATCH 054/297] introduce IEnvironmentService --- src/vs/code/electron-main/env.ts | 6 ++-- src/vs/code/electron-main/sharedProcess.ts | 2 +- src/vs/code/electron-main/windows.ts | 2 +- src/vs/code/node/argv.ts | 2 +- src/vs/code/node/sharedProcessMain.ts | 29 +++++++++++----- .../environment/common/environment.ts | 15 +++++++++ .../environment/node/environmentService.ts | 33 +++++++++++++++++++ src/vs/{code/node => platform}/package.ts | 0 src/vs/{code/node => platform}/product.ts | 0 .../darwin/cli.contribution.ts | 2 +- src/vs/workbench/node/userSettings.ts | 8 ++--- .../extensions/node/extensionsService.ts | 14 ++++---- .../extensions/node/vsoGalleryService.ts | 2 +- 13 files changed, 88 insertions(+), 27 deletions(-) create mode 100644 src/vs/platform/environment/common/environment.ts create mode 100644 src/vs/platform/environment/node/environmentService.ts rename src/vs/{code/node => platform}/package.ts (100%) rename src/vs/{code/node => platform}/product.ts (100%) diff --git a/src/vs/code/electron-main/env.ts b/src/vs/code/electron-main/env.ts index 3cb884ed3c0..87e7f01d791 100644 --- a/src/vs/code/electron-main/env.ts +++ b/src/vs/code/electron-main/env.ts @@ -17,9 +17,9 @@ import * as platform from 'vs/base/common/platform'; import URI from 'vs/base/common/uri'; import * as types from 'vs/base/common/types'; import { ServiceIdentifier, createDecorator } from 'vs/platform/instantiation/common/instantiation'; -import product, { IProductConfiguration } from 'vs/code/node/product'; +import product, { IProductConfiguration } from 'vs/platform/product'; import { parseArgs } from 'vs/code/node/argv'; -import pkg from 'vs/code/node/package'; +import pkg from 'vs/platform/package'; export interface IProcessEnvironment { [key: string]: string; @@ -46,7 +46,7 @@ export interface ICommandLineArguments { waitForWindowClose?: boolean; } -export const IEnvironmentService = createDecorator('environmentService'); +export const IEnvironmentService = createDecorator('mainEnvironmentService'); export interface IEnvironmentService { serviceId: ServiceIdentifier; diff --git a/src/vs/code/electron-main/sharedProcess.ts b/src/vs/code/electron-main/sharedProcess.ts index 399fd414b63..c21c6d0ba3f 100644 --- a/src/vs/code/electron-main/sharedProcess.ts +++ b/src/vs/code/electron-main/sharedProcess.ts @@ -5,7 +5,7 @@ import * as cp from 'child_process'; import URI from 'vs/base/common/uri'; -import pkg from 'vs/code/node/package'; +import pkg from 'vs/platform/package'; import { IDisposable } from 'vs/base/common/lifecycle'; import { assign } from 'vs/base/common/objects'; import { IEnvironment } from 'vs/platform/workspace/common/workspace'; diff --git a/src/vs/code/electron-main/windows.ts b/src/vs/code/electron-main/windows.ts index dea62c92247..8bf3c942a9c 100644 --- a/src/vs/code/electron-main/windows.ts +++ b/src/vs/code/electron-main/windows.ts @@ -12,7 +12,7 @@ import * as nls from 'vs/nls'; import * as paths from 'vs/base/common/paths'; import * as arrays from 'vs/base/common/arrays'; import * as objects from 'vs/base/common/objects'; -import pkg from 'vs/code/node/package'; +import pkg from 'vs/platform/package'; import { EventEmitter } from 'events'; import { IStorageService } from 'vs/code/electron-main/storage'; import { IPath, VSCodeWindow, ReadyState, IWindowConfiguration, IWindowState as ISingleWindowState, defaultWindowState } from 'vs/code/electron-main/window'; diff --git a/src/vs/code/node/argv.ts b/src/vs/code/node/argv.ts index 6d152123cba..bb63f21e289 100644 --- a/src/vs/code/node/argv.ts +++ b/src/vs/code/node/argv.ts @@ -5,7 +5,7 @@ import * as os from 'os'; import * as minimist from 'minimist'; -import pkg from 'vs/code/node/package'; +import pkg from 'vs/platform/package'; export interface ParsedArgs extends minimist.ParsedArgs { help: boolean; diff --git a/src/vs/code/node/sharedProcessMain.ts b/src/vs/code/node/sharedProcessMain.ts index f85149ea168..3ccba0d6b55 100644 --- a/src/vs/code/node/sharedProcessMain.ts +++ b/src/vs/code/node/sharedProcessMain.ts @@ -7,10 +7,16 @@ import * as fs from 'fs'; import * as platform from 'vs/base/common/platform'; import { serve, Server, connect } from 'vs/base/parts/ipc/node/ipc.net'; import { TPromise } from 'vs/base/common/winjs.base'; +import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; +import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; +import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService'; import { IConfiguration } from 'vs/platform/workspace/common/workspace'; -import { WorkspaceContextService } from 'vs/workbench/services/workspace/common/contextService'; +import { IEnvironmentService } from 'vs/platform/environment/common/environment'; +import { EnvironmentService } from 'vs/platform/environment/node/environmentService'; +import { IEventService } from 'vs/platform/event/common/event'; import { EventService } from 'vs/platform/event/common/eventService'; import { ExtensionsChannel } from 'vs/workbench/parts/extensions/common/extensionsIpc'; +import { IExtensionsService } from 'vs/workbench/parts/extensions/common/extensions'; import { ExtensionsService } from 'vs/workbench/parts/extensions/node/extensionsService'; interface IInitData { @@ -40,15 +46,22 @@ function setupPlanB(parentPid: number): void { } function main(server: Server, initData: IInitData): void { - const eventService = new EventService(); - const contextService = new WorkspaceContextService(eventService, null, initData.configuration, initData.contextServiceOptions); - const extensionService = new ExtensionsService(contextService); - const channel = new ExtensionsChannel(extensionService); + const services = new ServiceCollection(); - server.registerChannel('extensions', channel); + services.set(IEventService, new SyncDescriptor(EventService)); + services.set(IEnvironmentService, new SyncDescriptor(EnvironmentService)); + services.set(IExtensionsService, new SyncDescriptor(ExtensionsService)); - // eventually clean up old extensions - setTimeout(() => extensionService.removeDeprecatedExtensions(), 5000); + const instantiationService = new InstantiationService(services); + + instantiationService.invokeFunction(accessor => { + const extensionsService = accessor.get(IExtensionsService); + const channel = new ExtensionsChannel(extensionsService); + server.registerChannel('extensions', channel); + + // eventually clean up old extensions + setTimeout(() => (extensionsService as ExtensionsService).removeDeprecatedExtensions(), 5000); + }); } function setupIPC(hook: string): TPromise { diff --git a/src/vs/platform/environment/common/environment.ts b/src/vs/platform/environment/common/environment.ts new file mode 100644 index 00000000000..755271153d5 --- /dev/null +++ b/src/vs/platform/environment/common/environment.ts @@ -0,0 +1,15 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { createDecorator, ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation'; + +export const IEnvironmentService = createDecorator('environmentService'); + +export interface IEnvironmentService { + serviceId: ServiceIdentifier; + + userDataPath: string; + extensionsPath: string; +} diff --git a/src/vs/platform/environment/node/environmentService.ts b/src/vs/platform/environment/node/environmentService.ts new file mode 100644 index 00000000000..fb68bdd0beb --- /dev/null +++ b/src/vs/platform/environment/node/environmentService.ts @@ -0,0 +1,33 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { IEnvironmentService } from 'vs/platform/environment/common/environment'; +import * as paths from 'vs/base/node/paths'; +import product from 'vs/platform/product'; +import pkg from 'vs/platform/package'; +import * as os from 'os'; +import * as path from 'path'; +import { parseArgs } from 'vs/code/node/argv'; + +export class EnvironmentService implements IEnvironmentService { + + serviceId = IEnvironmentService; + + private _userDataPath: string; + get userDataPath(): string { return this._userDataPath; } + + private _extensionsPath: string; + get extensionsPath(): string { return this._extensionsPath; } + + constructor() { + const argv = parseArgs(process.argv); + + this._userDataPath = paths.getUserDataPath(process.platform, pkg.name, process.argv); + + const userHome = path.join(os.homedir(), product.dataFolderName); + this._extensionsPath = argv.extensionHomePath || path.join(userHome, 'extensions'); + this._extensionsPath = path.normalize(this._extensionsPath); + } +} \ No newline at end of file diff --git a/src/vs/code/node/package.ts b/src/vs/platform/package.ts similarity index 100% rename from src/vs/code/node/package.ts rename to src/vs/platform/package.ts diff --git a/src/vs/code/node/product.ts b/src/vs/platform/product.ts similarity index 100% rename from src/vs/code/node/product.ts rename to src/vs/platform/product.ts diff --git a/src/vs/workbench/electron-browser/darwin/cli.contribution.ts b/src/vs/workbench/electron-browser/darwin/cli.contribution.ts index 3bfe1e45b5c..22f1ad290a4 100644 --- a/src/vs/workbench/electron-browser/darwin/cli.contribution.ts +++ b/src/vs/workbench/electron-browser/darwin/cli.contribution.ts @@ -20,7 +20,7 @@ import { SyncActionDescriptor } from 'vs/platform/actions/common/actions'; import { IMessageService, Severity } from 'vs/platform/message/common/message'; import { IEditorService } from 'vs/platform/editor/common/editor'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import product from 'vs/code/node/product'; +import product from 'vs/platform/product'; interface ILegacyUse { file: string; diff --git a/src/vs/workbench/node/userSettings.ts b/src/vs/workbench/node/userSettings.ts index 812e9d44ffb..1ab54bb3bbb 100644 --- a/src/vs/workbench/node/userSettings.ts +++ b/src/vs/workbench/node/userSettings.ts @@ -13,7 +13,6 @@ import json = require('vs/base/common/json'); import objects = require('vs/base/common/objects'); import {TPromise} from 'vs/base/common/winjs.base'; import Event, {Emitter} from 'vs/base/common/event'; -import {IWorkspaceContextService} from 'vs/workbench/services/workspace/common/contextService'; export interface ISettings { settings: any; @@ -42,10 +41,11 @@ export class UserSettings { this.registerWatchers(); } - public static getValue(contextService: IWorkspaceContextService, key: string, fallback?: any): TPromise { - return new TPromise((c, e) => { - const appSettingsPath = contextService.getConfiguration().env.appSettingsPath; + public static getValue(userDataPath: string, key: string, fallback?: any): TPromise { + // TODO@joao cleanup! + const appSettingsPath = path.join(userDataPath, 'User', 'settings.json'); + return new TPromise((c, e) => { fs.readFile(appSettingsPath, (error /* ignore */, fileContents) => { let root = Object.create(null); let content = fileContents ? fileContents.toString() : '{}'; diff --git a/src/vs/workbench/parts/extensions/node/extensionsService.ts b/src/vs/workbench/parts/extensions/node/extensionsService.ts index 79f99718d11..32b9ec04134 100644 --- a/src/vs/workbench/parts/extensions/node/extensionsService.ts +++ b/src/vs/workbench/parts/extensions/node/extensionsService.ts @@ -17,14 +17,14 @@ import { Promise, TPromise } from 'vs/base/common/winjs.base'; import { IExtensionsService, IExtension, IExtensionManifest, IGalleryMetadata, IGalleryVersion } from 'vs/workbench/parts/extensions/common/extensions'; import { download, json, IRequestOptions } from 'vs/base/node/request'; import { getProxyAgent } from 'vs/base/node/proxy'; -import { IWorkspaceContextService } from 'vs/workbench/services/workspace/common/contextService'; +import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { Limiter } from 'vs/base/common/async'; import Event, { Emitter } from 'vs/base/common/event'; import { UserSettings } from 'vs/workbench/node/userSettings'; import * as semver from 'semver'; import { groupBy, values } from 'vs/base/common/collections'; import { isValidExtensionVersion } from 'vs/platform/extensions/node/extensionValidator'; -import pkg from 'vs/code/node/package'; +import pkg from 'vs/platform/package'; function parseManifest(raw: string): TPromise { return new Promise((c, e) => { @@ -104,10 +104,9 @@ export class ExtensionsService implements IExtensionsService { onDidUninstallExtension: Event = this._onDidUninstallExtension.event; constructor( - @IWorkspaceContextService private contextService: IWorkspaceContextService + @IEnvironmentService private environmentService: IEnvironmentService ) { - const env = contextService.getConfiguration().env; - this.extensionsPath = env.userExtensionsHome; + this.extensionsPath = environmentService.extensionsPath; this.obsoletePath = path.join(this.extensionsPath, '.obsolete'); this.obsoleteFileLimiter = new Limiter(1); } @@ -307,8 +306,9 @@ export class ExtensionsService implements IExtensionsService { // This should be pushed down and not rely on the context service private request(url: string): TPromise { const settings = TPromise.join([ - UserSettings.getValue(this.contextService, 'http.proxy'), - UserSettings.getValue(this.contextService, 'http.proxyStrictSSL') + // TODO@Joao we need a nice configuration service here! + UserSettings.getValue(this.environmentService.userDataPath, 'http.proxy'), + UserSettings.getValue(this.environmentService.userDataPath, 'http.proxyStrictSSL') ]); return settings.then(settings => { diff --git a/src/vs/workbench/parts/extensions/node/vsoGalleryService.ts b/src/vs/workbench/parts/extensions/node/vsoGalleryService.ts index 8f88612eeb9..969dc10ea6f 100644 --- a/src/vs/workbench/parts/extensions/node/vsoGalleryService.ts +++ b/src/vs/workbench/parts/extensions/node/vsoGalleryService.ts @@ -12,7 +12,7 @@ import { IRequestService } from 'vs/platform/request/common/request'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { matchesContiguousSubString } from 'vs/base/common/filters'; import { getExtensionId } from 'vs/workbench/parts/extensions/common/extensionsUtil'; -import product from 'vs/code/node/product'; +import product from 'vs/platform/product'; export interface IGalleryExtensionFile { assetType: string; From cc8b65c8c8a0b98a189a3d968b1f600ef55d62d7 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Wed, 4 May 2016 15:22:03 +0200 Subject: [PATCH 055/297] simplify shared process startup --- src/vs/code/electron-main/sharedProcess.ts | 54 +++------------------- src/vs/code/node/sharedProcessMain.ts | 14 ++---- 2 files changed, 11 insertions(+), 57 deletions(-) diff --git a/src/vs/code/electron-main/sharedProcess.ts b/src/vs/code/electron-main/sharedProcess.ts index c21c6d0ba3f..fcaa716732c 100644 --- a/src/vs/code/electron-main/sharedProcess.ts +++ b/src/vs/code/electron-main/sharedProcess.ts @@ -5,57 +5,21 @@ import * as cp from 'child_process'; import URI from 'vs/base/common/uri'; -import pkg from 'vs/platform/package'; import { IDisposable } from 'vs/base/common/lifecycle'; import { assign } from 'vs/base/common/objects'; -import { IEnvironment } from 'vs/platform/workspace/common/workspace'; -import { IEnvironmentService } from 'vs/code/electron-main/env'; -import { ISettingsService } from 'vs/code/electron-main/settings'; -import { IUpdateService } from 'vs/code/electron-main/update-manager'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; const boostrapPath = URI.parse(require.toUrl('bootstrap')).fsPath; -function getEnvironment(envService: IEnvironmentService, updateManager: IUpdateService): IEnvironment { - let configuration: IEnvironment = assign({}, envService.cliArgs); - configuration.execPath = process.execPath; - configuration.appName = envService.product.nameLong; - configuration.appRoot = envService.appRoot; - configuration.version = pkg.version; - configuration.commitHash = envService.product.commit; - configuration.appSettingsHome = envService.appSettingsHome; - configuration.appSettingsPath = envService.appSettingsPath; - configuration.appKeybindingsPath = envService.appKeybindingsPath; - configuration.userExtensionsHome = envService.userExtensionsHome; - configuration.isBuilt = envService.isBuilt; - configuration.updateFeedUrl = updateManager.feedUrl; - configuration.updateChannel = updateManager.channel; - configuration.extensionsGallery = envService.product.extensionsGallery; +function _spawnSharedProcess(): cp.ChildProcess { + const env = assign({}, process.env, { + AMD_ENTRYPOINT: 'vs/code/node/sharedProcessMain' + }); - return configuration; -} - -function _spawnSharedProcess(envService: IEnvironmentService, updateManager: IUpdateService, settingsManager: ISettingsService): cp.ChildProcess { - // Make sure the nls configuration travels to the shared process. - const opts = { - env: assign(assign({}, process.env), { - AMD_ENTRYPOINT: 'vs/code/node/sharedProcessMain' - }) - }; - - const result = cp.fork(boostrapPath, ['--type=SharedProcess'], opts); + const result = cp.fork(boostrapPath, ['--type=SharedProcess'], { env }); // handshake - result.once('message', () => { - result.send({ - configuration: { - env: getEnvironment(envService, updateManager) - }, - contextServiceOptions: { - globalSettings: settingsManager.globalSettings - } - }); - }); + result.once('message', () => result.send('hey')); return result; } @@ -63,10 +27,6 @@ function _spawnSharedProcess(envService: IEnvironmentService, updateManager: IUp let spawnCount = 0; export function spawnSharedProcess(accessor: ServicesAccessor): IDisposable { - const envService = accessor.get(IEnvironmentService); - const updateManager = accessor.get(IUpdateService); - const settingsManager = accessor.get(ISettingsService); - let child: cp.ChildProcess; const spawn = () => { @@ -74,7 +34,7 @@ export function spawnSharedProcess(accessor: ServicesAccessor): IDisposable { return; } - child = _spawnSharedProcess(envService, updateManager, settingsManager); + child = _spawnSharedProcess(); child.on('exit', spawn); }; diff --git a/src/vs/code/node/sharedProcessMain.ts b/src/vs/code/node/sharedProcessMain.ts index 3ccba0d6b55..944726966af 100644 --- a/src/vs/code/node/sharedProcessMain.ts +++ b/src/vs/code/node/sharedProcessMain.ts @@ -10,7 +10,6 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService'; -import { IConfiguration } from 'vs/platform/workspace/common/workspace'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { EnvironmentService } from 'vs/platform/environment/node/environmentService'; import { IEventService } from 'vs/platform/event/common/event'; @@ -19,11 +18,6 @@ import { ExtensionsChannel } from 'vs/workbench/parts/extensions/common/extensio import { IExtensionsService } from 'vs/workbench/parts/extensions/common/extensions'; import { ExtensionsService } from 'vs/workbench/parts/extensions/node/extensionsService'; -interface IInitData { - configuration: IConfiguration; - contextServiceOptions: { settings: any }; -} - function quit(err?: Error) { if (err) { console.error(err); @@ -45,7 +39,7 @@ function setupPlanB(parentPid: number): void { }, 5000); } -function main(server: Server, initData: IInitData): void { +function main(server: Server): void { const services = new ServiceCollection(); services.set(IEventService, new SyncDescriptor(EventService)); @@ -98,8 +92,8 @@ function setupIPC(hook: string): TPromise { return setup(true); } -function handshake(): TPromise { - return new TPromise((c, e) => { +function handshake(): TPromise { + return new TPromise((c, e) => { process.once('message', c); process.once('error', e); process.send('hello'); @@ -107,6 +101,6 @@ function handshake(): TPromise { } TPromise.join([setupIPC(process.env['VSCODE_SHARED_IPC_HOOK']), handshake()]) - .then(r => main(r[0], r[1])) + .then(r => main(r[0])) .then(() => setupPlanB(process.env['VSCODE_PID'])) .done(null, quit); \ No newline at end of file From 72f9c0b9b270670f0a991ccd3195b5c7a69aa3c3 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Wed, 4 May 2016 15:45:27 +0200 Subject: [PATCH 056/297] platform/extensionManagement --- src/vs/code/node/sharedProcessMain.ts | 14 ++++----- .../common/extensionManagement.ts} | 8 ++--- .../common/extensionManagementIpc.ts} | 14 ++++----- .../node/extensionGalleryService.ts} | 8 ++--- .../node/extensionManagementService.ts} | 6 ++-- .../node/extensionManagementUtil.ts} | 8 ++--- src/vs/workbench/electron-browser/shell.ts | 14 ++++----- src/vs/workbench/node/extensionHostMain.ts | 10 +++--- .../electron-browser/extensionTipsService.ts | 4 +-- .../extensions.contribution.ts | 6 ++-- .../electron-browser/extensionsActions.ts | 24 +++++++------- .../electron-browser/extensionsQuickOpen.ts | 31 ++++++++++--------- .../electron-browser/extensionsWidgets.ts | 17 +++++----- .../extensionsWorkbenchExtension.ts | 8 ++--- 14 files changed, 85 insertions(+), 87 deletions(-) rename src/vs/{workbench/parts/extensions/common/extensions.ts => platform/extensionManagement/common/extensionManagement.ts} (88%) rename src/vs/{workbench/parts/extensions/common/extensionsIpc.ts => platform/extensionManagement/common/extensionManagementIpc.ts} (85%) rename src/vs/{workbench/parts/extensions/node/vsoGalleryService.ts => platform/extensionManagement/node/extensionGalleryService.ts} (96%) rename src/vs/{workbench/parts/extensions/node/extensionsService.ts => platform/extensionManagement/node/extensionManagementService.ts} (97%) rename src/vs/{workbench/parts/extensions/common/extensionsUtil.ts => platform/extensionManagement/node/extensionManagementUtil.ts} (80%) diff --git a/src/vs/code/node/sharedProcessMain.ts b/src/vs/code/node/sharedProcessMain.ts index 944726966af..67d7c1a4c9a 100644 --- a/src/vs/code/node/sharedProcessMain.ts +++ b/src/vs/code/node/sharedProcessMain.ts @@ -14,9 +14,9 @@ import { IEnvironmentService } from 'vs/platform/environment/common/environment' import { EnvironmentService } from 'vs/platform/environment/node/environmentService'; import { IEventService } from 'vs/platform/event/common/event'; import { EventService } from 'vs/platform/event/common/eventService'; -import { ExtensionsChannel } from 'vs/workbench/parts/extensions/common/extensionsIpc'; -import { IExtensionsService } from 'vs/workbench/parts/extensions/common/extensions'; -import { ExtensionsService } from 'vs/workbench/parts/extensions/node/extensionsService'; +import { ExtensionManagementChannel } from 'vs/platform/extensionManagement/common/extensionManagementIpc'; +import { IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement'; +import { ExtensionManagementService } from 'vs/platform/extensionManagement/node/extensionManagementService'; function quit(err?: Error) { if (err) { @@ -44,17 +44,17 @@ function main(server: Server): void { services.set(IEventService, new SyncDescriptor(EventService)); services.set(IEnvironmentService, new SyncDescriptor(EnvironmentService)); - services.set(IExtensionsService, new SyncDescriptor(ExtensionsService)); + services.set(IExtensionManagementService, new SyncDescriptor(ExtensionManagementService)); const instantiationService = new InstantiationService(services); instantiationService.invokeFunction(accessor => { - const extensionsService = accessor.get(IExtensionsService); - const channel = new ExtensionsChannel(extensionsService); + const extensionManagementService = accessor.get(IExtensionManagementService); + const channel = new ExtensionManagementChannel(extensionManagementService); server.registerChannel('extensions', channel); // eventually clean up old extensions - setTimeout(() => (extensionsService as ExtensionsService).removeDeprecatedExtensions(), 5000); + setTimeout(() => (extensionManagementService as ExtensionManagementService).removeDeprecatedExtensions(), 5000); }); } diff --git a/src/vs/workbench/parts/extensions/common/extensions.ts b/src/vs/platform/extensionManagement/common/extensionManagement.ts similarity index 88% rename from src/vs/workbench/parts/extensions/common/extensions.ts rename to src/vs/platform/extensionManagement/common/extensionManagement.ts index e955dd28b6f..689a6514885 100644 --- a/src/vs/workbench/parts/extensions/common/extensions.ts +++ b/src/vs/platform/extensionManagement/common/extensionManagement.ts @@ -42,8 +42,8 @@ export interface IExtension extends IExtensionManifest { path?: string; } -export const IExtensionsService = createDecorator('extensionsService'); -export const IGalleryService = createDecorator('galleryService'); +export const IExtensionManagementService = createDecorator('extensionManagementService'); +export const IExtensionGalleryService = createDecorator('extensionGalleryService'); export interface IQueryOptions { text?: string; @@ -58,13 +58,13 @@ export interface IQueryResult { getPage(pageNumber: number): TPromise; } -export interface IGalleryService { +export interface IExtensionGalleryService { serviceId: ServiceIdentifier; isEnabled(): boolean; query(options?: IQueryOptions): TPromise; } -export interface IExtensionsService { +export interface IExtensionManagementService { serviceId: ServiceIdentifier; onInstallExtension: Event; onDidInstallExtension: Event<{ extension: IExtension; error?: Error; }>; diff --git a/src/vs/workbench/parts/extensions/common/extensionsIpc.ts b/src/vs/platform/extensionManagement/common/extensionManagementIpc.ts similarity index 85% rename from src/vs/workbench/parts/extensions/common/extensionsIpc.ts rename to src/vs/platform/extensionManagement/common/extensionManagementIpc.ts index 88121cbf2e2..debb987fea1 100644 --- a/src/vs/workbench/parts/extensions/common/extensionsIpc.ts +++ b/src/vs/platform/extensionManagement/common/extensionManagementIpc.ts @@ -7,10 +7,10 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { IChannel, eventToCall, eventFromCall } from 'vs/base/parts/ipc/common/ipc'; -import { IExtensionsService, IExtension, IExtensionManifest } from './extensions'; +import { IExtensionManagementService, IExtension, IExtensionManifest } from './extensionManagement'; import Event from 'vs/base/common/event'; -export interface IExtensionsChannel extends IChannel { +export interface IExtensionManagementChannel extends IChannel { call(command: 'event:onInstallExtension'): TPromise; call(command: 'event:onDidInstallExtension'): TPromise; call(command: 'event:onUninstallExtension'): TPromise; @@ -21,9 +21,9 @@ export interface IExtensionsChannel extends IChannel { call(command: string, arg: any): TPromise; } -export class ExtensionsChannel implements IExtensionsChannel { +export class ExtensionManagementChannel implements IExtensionManagementChannel { - constructor(private service: IExtensionsService) { } + constructor(private service: IExtensionManagementService) { } call(command: string, arg: any): TPromise { switch (command) { @@ -38,11 +38,11 @@ export class ExtensionsChannel implements IExtensionsChannel { } } -export class ExtensionsChannelClient implements IExtensionsService { +export class ExtensionManagementChannelClient implements IExtensionManagementService { - serviceId = IExtensionsService; + serviceId = IExtensionManagementService; - constructor(private channel: IExtensionsChannel) { } + constructor(private channel: IExtensionManagementChannel) { } private _onInstallExtension = eventFromCall(this.channel, 'event:onInstallExtension'); get onInstallExtension(): Event { return this._onInstallExtension; } diff --git a/src/vs/workbench/parts/extensions/node/vsoGalleryService.ts b/src/vs/platform/extensionManagement/node/extensionGalleryService.ts similarity index 96% rename from src/vs/workbench/parts/extensions/node/vsoGalleryService.ts rename to src/vs/platform/extensionManagement/node/extensionGalleryService.ts index 969dc10ea6f..c283f2bc608 100644 --- a/src/vs/workbench/parts/extensions/node/vsoGalleryService.ts +++ b/src/vs/platform/extensionManagement/node/extensionGalleryService.ts @@ -4,14 +4,14 @@ *--------------------------------------------------------------------------------------------*/ import { TPromise } from 'vs/base/common/winjs.base'; -import { IExtension, IGalleryService, IGalleryVersion, IQueryOptions, IQueryResult } from 'vs/workbench/parts/extensions/common/extensions'; +import { IExtension, IExtensionGalleryService, IGalleryVersion, IQueryOptions, IQueryResult } from 'vs/platform/extensionManagement/common/extensionManagement'; import { isUndefined } from 'vs/base/common/types'; import { IXHRResponse } from 'vs/base/common/http'; import { assign, getOrDefault } from 'vs/base/common/objects'; import { IRequestService } from 'vs/platform/request/common/request'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { matchesContiguousSubString } from 'vs/base/common/filters'; -import { getExtensionId } from 'vs/workbench/parts/extensions/common/extensionsUtil'; +import { getExtensionId } from 'vs/platform/extensionManagement/node/extensionManagementUtil'; import product from 'vs/platform/product'; export interface IGalleryExtensionFile { @@ -201,9 +201,9 @@ function extensionFilter(input: string): (e: IExtension) => boolean { }; } -export class GalleryService implements IGalleryService { +export class GalleryService implements IExtensionGalleryService { - serviceId = IGalleryService; + serviceId = IExtensionGalleryService; private extensionsGalleryUrl: string; private extensionsCacheUrl: string; diff --git a/src/vs/workbench/parts/extensions/node/extensionsService.ts b/src/vs/platform/extensionManagement/node/extensionManagementService.ts similarity index 97% rename from src/vs/workbench/parts/extensions/node/extensionsService.ts rename to src/vs/platform/extensionManagement/node/extensionManagementService.ts index 32b9ec04134..5009f79b4f1 100644 --- a/src/vs/workbench/parts/extensions/node/extensionsService.ts +++ b/src/vs/platform/extensionManagement/node/extensionManagementService.ts @@ -14,7 +14,7 @@ import { assign } from 'vs/base/common/objects'; import { flatten } from 'vs/base/common/arrays'; import { extract, buffer } from 'vs/base/node/zip'; import { Promise, TPromise } from 'vs/base/common/winjs.base'; -import { IExtensionsService, IExtension, IExtensionManifest, IGalleryMetadata, IGalleryVersion } from 'vs/workbench/parts/extensions/common/extensions'; +import { IExtensionManagementService, IExtension, IExtensionManifest, IGalleryMetadata, IGalleryVersion } from 'vs/platform/extensionManagement/common/extensionManagement'; import { download, json, IRequestOptions } from 'vs/base/node/request'; import { getProxyAgent } from 'vs/base/node/proxy'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; @@ -83,9 +83,9 @@ function getExtensionId(extension: IExtensionManifest, version = extension.versi return `${ extension.publisher }.${ extension.name }-${ version }`; } -export class ExtensionsService implements IExtensionsService { +export class ExtensionManagementService implements IExtensionManagementService { - serviceId = IExtensionsService; + serviceId = IExtensionManagementService; private extensionsPath: string; private obsoletePath: string; diff --git a/src/vs/workbench/parts/extensions/common/extensionsUtil.ts b/src/vs/platform/extensionManagement/node/extensionManagementUtil.ts similarity index 80% rename from src/vs/workbench/parts/extensions/common/extensionsUtil.ts rename to src/vs/platform/extensionManagement/node/extensionManagementUtil.ts index ae487529d18..16e731698e5 100644 --- a/src/vs/workbench/parts/extensions/common/extensionsUtil.ts +++ b/src/vs/platform/extensionManagement/node/extensionManagementUtil.ts @@ -5,8 +5,7 @@ 'use strict'; -import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; -import { IExtension, IExtensionsService, IGalleryService } from 'vs/workbench/parts/extensions/common/extensions'; +import { IExtension, IExtensionManagementService, IExtensionGalleryService } from 'vs/platform/extensionManagement/common/extensionManagement'; import { TPromise } from 'vs/base/common/winjs.base'; import * as semver from 'semver'; @@ -29,10 +28,7 @@ export function getTelemetryData(extension: IExtension): any { }; } -export function getOutdatedExtensions(accessor: ServicesAccessor): TPromise { - const extensionsService = accessor.get(IExtensionsService); - const galleryService = accessor.get(IGalleryService); - +export function getOutdatedExtensions(extensionsService: IExtensionManagementService, galleryService: IExtensionGalleryService): TPromise { if (!galleryService.isEnabled()) { return TPromise.as([]); } diff --git a/src/vs/workbench/electron-browser/shell.ts b/src/vs/workbench/electron-browser/shell.ts index f6d45a7834b..cdfed4b3532 100644 --- a/src/vs/workbench/electron-browser/shell.ts +++ b/src/vs/workbench/electron-browser/shell.ts @@ -65,8 +65,8 @@ import {IThemeService} from 'vs/workbench/services/themes/common/themeService'; import {ThemeService} from 'vs/workbench/services/themes/electron-browser/themeService'; import {getDelayedChannel} from 'vs/base/parts/ipc/common/ipc'; import {connect} from 'vs/base/parts/ipc/node/ipc.net'; -import {IExtensionsChannel, ExtensionsChannelClient} from 'vs/workbench/parts/extensions/common/extensionsIpc'; -import {IExtensionsService} from 'vs/workbench/parts/extensions/common/extensions'; +import {IExtensionManagementChannel, ExtensionManagementChannelClient} from 'vs/platform/extensionManagement/common/extensionManagementIpc'; +import {IExtensionManagementService} from 'vs/platform/extensionManagement/common/extensionManagement'; import {ReloadWindowAction} from 'vs/workbench/electron-browser/actions'; import 'vs/platform/opener/electron-browser/opener.contribution'; // self registering service @@ -271,12 +271,12 @@ export class WorkbenchShell { serviceCollection.set(ICodeEditorService, new CodeEditorServiceImpl()); serviceCollection.set(IEditorWorkerService, editorWorkerService); serviceCollection.set(IThemeService, this.themeService); - serviceCollection.set(IExtensionsService, new ExtensionsChannelClient(this.initSharedProcessChannel(instantiationService, this.messageService))); + serviceCollection.set(IExtensionManagementService, new ExtensionManagementChannelClient(this.initSharedProcessChannel(instantiationService, this.messageService))); return [instantiationService, serviceCollection]; } - private initSharedProcessChannel(instantiationService: IInstantiationService, messageService: IMessageService): IExtensionsChannel { + private initSharedProcessChannel(instantiationService: IInstantiationService, messageService: IMessageService): IExtensionManagementChannel { const sharedProcessClientPromise = connect(process.env['VSCODE_SHARED_IPC_HOOK']); sharedProcessClientPromise.done(service => { @@ -288,10 +288,10 @@ export class WorkbenchShell { }); }, errors.onUnexpectedError); - const extensionsChannelPromise = sharedProcessClientPromise - .then(client => client.getChannel('extensions')); + const extensionManagementChannelPromise = sharedProcessClientPromise + .then(client => client.getChannel('extensions')); - return getDelayedChannel(extensionsChannelPromise); + return getDelayedChannel(extensionManagementChannelPromise); } public open(): void { diff --git a/src/vs/workbench/node/extensionHostMain.ts b/src/vs/workbench/node/extensionHostMain.ts index 6d4c95a9596..773f3af968a 100644 --- a/src/vs/workbench/node/extensionHostMain.ts +++ b/src/vs/workbench/node/extensionHostMain.ts @@ -26,8 +26,8 @@ import {BaseWorkspaceContextService} from 'vs/platform/workspace/common/baseWork import {ExtensionScanner, MessagesCollector} from 'vs/workbench/node/extensionPoints'; import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace'; import {Client} from 'vs/base/parts/ipc/node/ipc.net'; -import {IExtensionsChannel, ExtensionsChannelClient} from 'vs/workbench/parts/extensions/common/extensionsIpc'; -import {IExtensionsService} from 'vs/workbench/parts/extensions/common/extensions'; +import {IExtensionManagementService} from 'vs/platform/extensionManagement/common/extensionManagement'; +import {IExtensionManagementChannel, ExtensionManagementChannelClient} from 'vs/platform/extensionManagement/common/extensionManagementIpc'; const DIRNAME = URI.parse(require.toUrl('./')).fsPath; const BASE_PATH = paths.normalize(paths.join(DIRNAME, '../../../..')); @@ -65,9 +65,9 @@ export function createServices(remoteCom: IMainProcessExtHostIPC, initData: IIni services.set(IExtensionService, new ExtHostExtensionService(threadService, telemetryService)); // Connect to shared process services - const channel = sharedProcessClient.getChannel('extensions'); - const extensionsService = new ExtensionsChannelClient(channel); - services.set(IExtensionsService, extensionsService); + const channel = sharedProcessClient.getChannel('extensions'); + const extensionsService = new ExtensionManagementChannelClient(channel); + services.set(IExtensionManagementService, extensionsService); let instantiationService = new InstantiationService(services, true); threadService.setInstantiationService(instantiationService); diff --git a/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.ts b/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.ts index fc317d47af6..2872043300d 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.ts +++ b/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.ts @@ -8,7 +8,7 @@ import {forEach} from 'vs/base/common/collections'; import {IDisposable, dispose} from 'vs/base/common/lifecycle'; import {TPromise as Promise} from 'vs/base/common/winjs.base'; import {match} from 'vs/base/common/glob'; -import {IGalleryService, IExtensionTipsService, IExtension} from 'vs/workbench/parts/extensions/common/extensions'; +import {IExtensionGalleryService, IExtensionTipsService, IExtension} from 'vs/platform/extensionManagement/common/extensionManagement'; import {IModelService} from 'vs/editor/common/services/modelService'; import {IStorageService, StorageScope} from 'vs/platform/storage/common/storage'; import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace'; @@ -22,7 +22,7 @@ export class ExtensionTipsService implements IExtensionTipsService { private _disposables: IDisposable[] = []; constructor( - @IGalleryService private _galleryService: IGalleryService, + @IExtensionGalleryService private _galleryService: IExtensionGalleryService, @IModelService private _modelService: IModelService, @IStorageService private _storageService: IStorageService, @IWorkspaceContextService contextService: IWorkspaceContextService diff --git a/src/vs/workbench/parts/extensions/electron-browser/extensions.contribution.ts b/src/vs/workbench/parts/extensions/electron-browser/extensions.contribution.ts index 8728eeac1fb..45b7d92718f 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/extensions.contribution.ts +++ b/src/vs/workbench/parts/extensions/electron-browser/extensions.contribution.ts @@ -8,14 +8,14 @@ import { Registry } from 'vs/platform/platform'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { IStatusbarRegistry, Extensions as StatusbarExtensions, StatusbarItemDescriptor, StatusbarAlignment } from 'vs/workbench/browser/parts/statusbar/statusbar'; import { ExtensionsStatusbarItem } from 'vs/workbench/parts/extensions/electron-browser/extensionsWidgets'; -import { IGalleryService, IExtensionTipsService, ExtensionsLabel, ExtensionsChannelId } from 'vs/workbench/parts/extensions/common/extensions'; -import { GalleryService } from 'vs/workbench/parts/extensions/node/vsoGalleryService'; +import { IExtensionGalleryService, IExtensionTipsService, ExtensionsLabel, ExtensionsChannelId } from 'vs/platform/extensionManagement/common/extensionManagement'; +import { GalleryService } from 'vs/platform/extensionManagement/node/extensionGalleryService'; import { ExtensionTipsService } from 'vs/workbench/parts/extensions/electron-browser/extensionTipsService'; import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions'; import { ExtensionsWorkbenchExtension } from 'vs/workbench/parts/extensions/electron-browser/extensionsWorkbenchExtension'; import { IOutputChannelRegistry, Extensions as OutputExtensions } from 'vs/workbench/parts/output/common/output'; -registerSingleton(IGalleryService, GalleryService); +registerSingleton(IExtensionGalleryService, GalleryService); registerSingleton(IExtensionTipsService, ExtensionTipsService); Registry.as(WorkbenchExtensions.Workbench) diff --git a/src/vs/workbench/parts/extensions/electron-browser/extensionsActions.ts b/src/vs/workbench/parts/extensions/electron-browser/extensionsActions.ts index b6033bddfdc..a7e0780b4ea 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/extensionsActions.ts +++ b/src/vs/workbench/parts/extensions/electron-browser/extensionsActions.ts @@ -12,8 +12,8 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IMessageService } from 'vs/platform/message/common/message'; import { ReloadWindowAction } from 'vs/workbench/electron-browser/actions'; -import { IExtensionsService, IExtension } from 'vs/workbench/parts/extensions/common/extensions'; -import { extensionEquals, getTelemetryData } from 'vs/workbench/parts/extensions/common/extensionsUtil'; +import { IExtensionManagementService, IExtension } from 'vs/platform/extensionManagement/common/extensionManagement'; +import { extensionEquals, getTelemetryData } from 'vs/platform/extensionManagement/node/extensionManagementUtil'; import { IQuickOpenService } from 'vs/workbench/services/quickopen/common/quickOpenService'; const CloseAction = new Action('action.close', nls.localize('close', "Close")); @@ -26,7 +26,7 @@ export class ListExtensionsAction extends Action { constructor( id: string, label: string, - @IExtensionsService private extensionsService: IExtensionsService, + @IExtensionManagementService private extensionManagementService: IExtensionManagementService, @IQuickOpenService private quickOpenService: IQuickOpenService ) { super(id, label, null, true); @@ -49,7 +49,7 @@ export class InstallExtensionAction extends Action { constructor( id: string, label: string, - @IExtensionsService private extensionsService: IExtensionsService, + @IExtensionManagementService private extensionManagementService: IExtensionManagementService, @IQuickOpenService private quickOpenService: IQuickOpenService ) { super(id, label, null, true); @@ -72,7 +72,7 @@ export class ListOutdatedExtensionsAction extends Action { constructor( id: string, label: string, - @IExtensionsService private extensionsService: IExtensionsService, + @IExtensionManagementService private extensionManagementService: IExtensionManagementService, @IQuickOpenService private quickOpenService: IQuickOpenService ) { super(id, label, null, true); @@ -95,7 +95,7 @@ export class ListSuggestedExtensionsAction extends Action { constructor( id: string, label: string, - @IExtensionsService private extensionsService: IExtensionsService, + @IExtensionManagementService private extensionManagementService: IExtensionManagementService, @IQuickOpenService private quickOpenService: IQuickOpenService ) { super(id, label, null, true); @@ -115,7 +115,7 @@ export class InstallAction extends Action { constructor( label: string, @IQuickOpenService protected quickOpenService: IQuickOpenService, - @IExtensionsService protected extensionsService: IExtensionsService, + @IExtensionManagementService protected extensionManagementService: IExtensionManagementService, @IMessageService protected messageService: IMessageService, @ITelemetryService protected telemetryService: ITelemetryService, @IInstantiationService protected instantiationService: IInstantiationService @@ -126,10 +126,10 @@ export class InstallAction extends Action { public run(extension: IExtension): TPromise { this.enabled = false; - return this.extensionsService.getInstalled() + return this.extensionManagementService.getInstalled() .then(installed => installed.some(e => extensionEquals(e, extension))) .then(isUpdate => { - return this.extensionsService + return this.extensionManagementService .install(extension) .then(() => this.onSuccess(extension, isUpdate), err => this.onError(err, extension, isUpdate)) .then(() => this.enabled = true) @@ -165,7 +165,7 @@ export class UninstallAction extends Action { constructor( @IQuickOpenService protected quickOpenService: IQuickOpenService, - @IExtensionsService protected extensionsService: IExtensionsService, + @IExtensionManagementService protected extensionManagementService: IExtensionManagementService, @IMessageService protected messageService: IMessageService, @ITelemetryService protected telemetryService: ITelemetryService, @IInstantiationService protected instantiationService: IInstantiationService @@ -180,14 +180,14 @@ export class UninstallAction extends Action { this.enabled = false; - return this.extensionsService.getInstalled().then(localExtensions => { + return this.extensionManagementService.getInstalled().then(localExtensions => { const [local] = localExtensions.filter(local => extensionEquals(local, extension)); if (!local) { return TPromise.wrapError(nls.localize('notFound', "Extension '{0}' not installed.", extension.displayName)); } - return this.extensionsService.uninstall(local) + return this.extensionManagementService.uninstall(local) .then(() => this.onSuccess(local), err => this.onError(err, local)) .then(() => this.enabled = true) .then(() => null); diff --git a/src/vs/workbench/parts/extensions/electron-browser/extensionsQuickOpen.ts b/src/vs/workbench/parts/extensions/electron-browser/extensionsQuickOpen.ts index 81f6cf604b6..c3c55e7e169 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/extensionsQuickOpen.ts +++ b/src/vs/workbench/parts/extensions/electron-browser/extensionsQuickOpen.ts @@ -17,7 +17,7 @@ import { QuickOpenPagedModel, IPagedRenderer } from 'vs/base/parts/quickopen/com import { matchesContiguousSubString } from 'vs/base/common/filters'; import { QuickOpenHandler } from 'vs/workbench/browser/quickopen'; import { IHighlight } from 'vs/base/parts/quickopen/browser/quickOpenModel'; -import { IExtensionsService, IGalleryService, IExtensionTipsService, IExtension, IQueryResult } from 'vs/workbench/parts/extensions/common/extensions'; +import { IExtensionManagementService, IExtensionGalleryService, IExtensionTipsService, IExtension, IQueryResult } from 'vs/platform/extensionManagement/common/extensionManagement'; import { InstallAction, UninstallAction } from 'vs/workbench/parts/extensions/electron-browser/extensionsActions'; import { IMessageService } from 'vs/platform/message/common/message'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; @@ -27,7 +27,7 @@ import { HighlightedLabel } from 'vs/base/browser/ui/highlightedlabel/highlighte import { Action } from 'vs/base/common/actions'; import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; import { shell } from 'electron'; -import { extensionEquals, getOutdatedExtensions } from 'vs/workbench/parts/extensions/common/extensionsUtil'; +import { extensionEquals, getOutdatedExtensions } from 'vs/platform/extensionManagement/node/extensionManagementUtil'; const $ = dom.emmet; @@ -186,7 +186,7 @@ class Renderer implements IPagedRenderer { constructor( @IInstantiationService private instantiationService: IInstantiationService, - @IExtensionsService private extensionsService: IExtensionsService + @IExtensionManagementService private extensionManagementService: IExtensionManagementService ) {} getHeight(entry: IExtensionEntry): number { @@ -279,8 +279,8 @@ class Renderer implements IPagedRenderer { updateActions(); data.disposables = dispose(data.disposables); - data.disposables.push(this.extensionsService.onDidInstallExtension(e => onExtensionStateChange(e.extension, ExtensionState.Installed))); - data.disposables.push(this.extensionsService.onDidUninstallExtension(e => onExtensionStateChange(e, ExtensionState.Uninstalled))); + data.disposables.push(this.extensionManagementService.onDidInstallExtension(e => onExtensionStateChange(e.extension, ExtensionState.Installed))); + data.disposables.push(this.extensionManagementService.onDidUninstallExtension(e => onExtensionStateChange(e, ExtensionState.Uninstalled))); data.displayName.set(extension.displayName, entry.highlights.displayName); data.displayName.element.title = extension.name; @@ -370,7 +370,7 @@ export class LocalExtensionsHandler extends QuickOpenHandler { constructor( @IInstantiationService private instantiationService: IInstantiationService, - @IExtensionsService private extensionsService: IExtensionsService + @IExtensionManagementService private extensionManagementService: IExtensionManagementService ) { super(); this.modelPromise = null; @@ -382,7 +382,7 @@ export class LocalExtensionsHandler extends QuickOpenHandler { getResults(input: string): TPromise> { if (!this.modelPromise) { - this.modelPromise = this.extensionsService.getInstalled() + this.modelPromise = this.extensionManagementService.getInstalled() .then(extensions => this.instantiationService.createInstance(LocalExtensionsModel, extensions)); } @@ -411,8 +411,8 @@ export class GalleryExtensionsHandler extends QuickOpenHandler { constructor( @IInstantiationService private instantiationService: IInstantiationService, - @IExtensionsService private extensionsService: IExtensionsService, - @IGalleryService private galleryService: IGalleryService, + @IExtensionManagementService private extensionManagementService: IExtensionManagementService, + @IExtensionGalleryService private galleryService: IExtensionGalleryService, @ITelemetryService private telemetryService: ITelemetryService ) { super(); @@ -424,7 +424,7 @@ export class GalleryExtensionsHandler extends QuickOpenHandler { } getResults(text: string): TPromise> { - return this.extensionsService.getInstalled().then(localExtensions => { + return this.extensionManagementService.getInstalled().then(localExtensions => { return this.delayer.trigger(() => this.galleryService.query({ text })).then((result: IQueryResult) => { const pager = mapPager(result, extension => { const [local] = localExtensions.filter(local => extensionEquals(local, extension)); @@ -493,8 +493,8 @@ export class OutdatedExtensionsHandler extends QuickOpenHandler { constructor( @IInstantiationService private instantiationService: IInstantiationService, - @IExtensionsService private extensionsService: IExtensionsService, - @IGalleryService private galleryService: IGalleryService, + @IExtensionManagementService private extensionManagementService: IExtensionManagementService, + @IExtensionGalleryService private galleryService: IExtensionGalleryService, @ITelemetryService private telemetryService: ITelemetryService ) { super(); @@ -507,7 +507,8 @@ export class OutdatedExtensionsHandler extends QuickOpenHandler { getResults(input: string): TPromise> { if (!this.modelPromise) { this.telemetryService.publicLog('extensionGallery:open'); - this.modelPromise = this.instantiationService.invokeFunction(getOutdatedExtensions) + + this.modelPromise = getOutdatedExtensions(this.extensionManagementService, this.galleryService) .then(outdated => this.instantiationService.createInstance(OutdatedExtensionsModel, outdated)); } @@ -575,7 +576,7 @@ export class SuggestedExtensionHandler extends QuickOpenHandler { @IExtensionTipsService private extensionTipsService: IExtensionTipsService, @IInstantiationService private instantiationService: IInstantiationService, @ITelemetryService private telemetryService: ITelemetryService, - @IExtensionsService private extensionsService: IExtensionsService + @IExtensionManagementService private extensionManagementService: IExtensionManagementService ) { super(); } @@ -583,7 +584,7 @@ export class SuggestedExtensionHandler extends QuickOpenHandler { getResults(input: string): TPromise> { if (!this.modelPromise) { this.telemetryService.publicLog('extensionRecommendations:open'); - this.modelPromise = TPromise.join([this.extensionTipsService.getRecommendations(), this.extensionsService.getInstalled()]) + this.modelPromise = TPromise.join([this.extensionTipsService.getRecommendations(), this.extensionManagementService.getInstalled()]) .then(result => this.instantiationService.createInstance(SuggestedExtensionsModel, result[0], result[1])); } diff --git a/src/vs/workbench/parts/extensions/electron-browser/extensionsWidgets.ts b/src/vs/workbench/parts/extensions/electron-browser/extensionsWidgets.ts index 07e928f715f..01dab50a167 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/extensionsWidgets.ts +++ b/src/vs/workbench/parts/extensions/electron-browser/extensionsWidgets.ts @@ -15,9 +15,9 @@ import { IStatusbarItem } from 'vs/workbench/browser/parts/statusbar/statusbar'; import { IOutputService } from 'vs/workbench/parts/output/common/output'; import { IExtensionService, IMessage } from 'vs/platform/extensions/common/extensions'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { IExtensionsService, ExtensionsLabel, ExtensionsChannelId, IExtension, IExtensionManifest } from 'vs/workbench/parts/extensions/common/extensions'; +import { IExtensionManagementService, IExtensionGalleryService, ExtensionsLabel, ExtensionsChannelId, IExtension, IExtensionManifest } from 'vs/platform/extensionManagement/common/extensionManagement'; import { IQuickOpenService } from 'vs/workbench/services/quickopen/common/quickOpenService'; -import { getOutdatedExtensions } from 'vs/workbench/parts/extensions/common/extensionsUtil'; +import { getOutdatedExtensions } from 'vs/platform/extensionManagement/node/extensionManagementUtil'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; interface IState { @@ -47,7 +47,8 @@ export class ExtensionsStatusbarItem implements IStatusbarItem { constructor( @IExtensionService private extensionService: IExtensionService, @IOutputService private outputService: IOutputService, - @IExtensionsService protected extensionsService: IExtensionsService, + @IExtensionManagementService protected extensionManagementService: IExtensionManagementService, + @IExtensionGalleryService protected extensionGalleryService: IExtensionGalleryService, @IInstantiationService protected instantiationService: IInstantiationService, @IQuickOpenService protected quickOpenService: IQuickOpenService, @ITelemetryService protected telemetrService: ITelemetryService @@ -62,9 +63,9 @@ export class ExtensionsStatusbarItem implements IStatusbarItem { this.checkOutdated(); const disposables = []; - this.extensionsService.onInstallExtension(this.onInstallExtension, this, disposables); - this.extensionsService.onDidInstallExtension(this.onDidInstallExtension, this, disposables); - this.extensionsService.onDidUninstallExtension(this.onDidUninstallExtension, this, disposables); + this.extensionManagementService.onInstallExtension(this.onInstallExtension, this, disposables); + this.extensionManagementService.onDidInstallExtension(this.onDidInstallExtension, this, disposables); + this.extensionManagementService.onDidUninstallExtension(this.onDidUninstallExtension, this, disposables); return combinedDisposable(disposables); } @@ -113,7 +114,7 @@ export class ExtensionsStatusbarItem implements IStatusbarItem { } private showErrors(errors: IMessage[]): void { - const promise = onUnexpectedPromiseError(this.extensionsService.getInstalled()); + const promise = onUnexpectedPromiseError(this.extensionManagementService.getInstalled()); promise.done(installed => { errors.forEach(m => { const extension = installed.filter(ext => ext.path === m.source).pop(); @@ -157,7 +158,7 @@ export class ExtensionsStatusbarItem implements IStatusbarItem { } private checkOutdated(): TPromise { - return this.instantiationService.invokeFunction(getOutdatedExtensions) + return getOutdatedExtensions(this.extensionManagementService, this.extensionGalleryService) .then(null, _ => []) // ignore errors .then(outdated => { this.updateState({ outdated }); diff --git a/src/vs/workbench/parts/extensions/electron-browser/extensionsWorkbenchExtension.ts b/src/vs/workbench/parts/extensions/electron-browser/extensionsWorkbenchExtension.ts index ca0eef81217..1fdb6ab2337 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/extensionsWorkbenchExtension.ts +++ b/src/vs/workbench/parts/extensions/electron-browser/extensionsWorkbenchExtension.ts @@ -8,7 +8,7 @@ import errors = require('vs/base/common/errors'); import platform = require('vs/platform/platform'); import { Promise } from 'vs/base/common/winjs.base'; import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; -import { IExtensionsService, IGalleryService, IExtensionTipsService, ExtensionsLabel } from 'vs/workbench/parts/extensions/common/extensions'; +import { IExtensionManagementService, IExtensionGalleryService, IExtensionTipsService, ExtensionsLabel } from 'vs/platform/extensionManagement/common/extensionManagement'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IMessageService } from 'vs/platform/message/common/message'; import Severity from 'vs/base/common/severity'; @@ -28,11 +28,11 @@ export class ExtensionsWorkbenchExtension implements IWorkbenchContribution { constructor( @IInstantiationService private instantiationService: IInstantiationService, - @IExtensionsService private extensionsService: IExtensionsService, + @IExtensionManagementService private extensionManagementService: IExtensionManagementService, @IMessageService private messageService: IMessageService, @IWorkspaceContextService contextService: IWorkspaceContextService, @IExtensionTipsService extenstionTips: IExtensionTipsService, // this is to eagerly start the service - @IGalleryService galleryService: IGalleryService + @IExtensionGalleryService galleryService: IExtensionGalleryService ) { this.registerListeners(); @@ -102,7 +102,7 @@ export class ExtensionsWorkbenchExtension implements IWorkbenchContribution { } private install(extensions: string[]): Promise { - return Promise.join(extensions.map(extPath => this.extensionsService.install(extPath))) + return Promise.join(extensions.map(extPath => this.extensionManagementService.install(extPath))) .then(extensions => { this.messageService.show( Severity.Info, From a4c726c68fc3d88ed581cf0a88050b6f67af52a2 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Wed, 4 May 2016 16:44:57 +0200 Subject: [PATCH 057/297] ExtensionGalleryService --- .../extensionManagement/node/extensionGalleryService.ts | 2 +- .../extensions/electron-browser/extensions.contribution.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/platform/extensionManagement/node/extensionGalleryService.ts b/src/vs/platform/extensionManagement/node/extensionGalleryService.ts index c283f2bc608..0ec73c9de2f 100644 --- a/src/vs/platform/extensionManagement/node/extensionGalleryService.ts +++ b/src/vs/platform/extensionManagement/node/extensionGalleryService.ts @@ -201,7 +201,7 @@ function extensionFilter(input: string): (e: IExtension) => boolean { }; } -export class GalleryService implements IExtensionGalleryService { +export class ExtensionGalleryService implements IExtensionGalleryService { serviceId = IExtensionGalleryService; diff --git a/src/vs/workbench/parts/extensions/electron-browser/extensions.contribution.ts b/src/vs/workbench/parts/extensions/electron-browser/extensions.contribution.ts index 45b7d92718f..c24649dc1bf 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/extensions.contribution.ts +++ b/src/vs/workbench/parts/extensions/electron-browser/extensions.contribution.ts @@ -9,13 +9,13 @@ import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { IStatusbarRegistry, Extensions as StatusbarExtensions, StatusbarItemDescriptor, StatusbarAlignment } from 'vs/workbench/browser/parts/statusbar/statusbar'; import { ExtensionsStatusbarItem } from 'vs/workbench/parts/extensions/electron-browser/extensionsWidgets'; import { IExtensionGalleryService, IExtensionTipsService, ExtensionsLabel, ExtensionsChannelId } from 'vs/platform/extensionManagement/common/extensionManagement'; -import { GalleryService } from 'vs/platform/extensionManagement/node/extensionGalleryService'; +import { ExtensionGalleryService } from 'vs/platform/extensionManagement/node/extensionGalleryService'; import { ExtensionTipsService } from 'vs/workbench/parts/extensions/electron-browser/extensionTipsService'; import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions'; import { ExtensionsWorkbenchExtension } from 'vs/workbench/parts/extensions/electron-browser/extensionsWorkbenchExtension'; import { IOutputChannelRegistry, Extensions as OutputExtensions } from 'vs/workbench/parts/output/common/output'; -registerSingleton(IExtensionGalleryService, GalleryService); +registerSingleton(IExtensionGalleryService, ExtensionGalleryService); registerSingleton(IExtensionTipsService, ExtensionTipsService); Registry.as(WorkbenchExtensions.Workbench) From 3726898b2140a505134779373e96b26db4c5c262 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Wed, 4 May 2016 16:45:20 +0200 Subject: [PATCH 058/297] NodeRequestService --- src/vs/platform/request/common/request.ts | 6 +- .../request/node/nodeRequestService.ts | 123 ++++++++++++++++++ 2 files changed, 126 insertions(+), 3 deletions(-) create mode 100644 src/vs/platform/request/node/nodeRequestService.ts diff --git a/src/vs/platform/request/common/request.ts b/src/vs/platform/request/common/request.ts index 143c2145ec6..b2f091b5360 100644 --- a/src/vs/platform/request/common/request.ts +++ b/src/vs/platform/request/common/request.ts @@ -5,8 +5,8 @@ 'use strict'; import http = require('vs/base/common/http'); -import winjs = require('vs/base/common/winjs.base'); -import {createDecorator, ServiceIdentifier} from 'vs/platform/instantiation/common/instantiation'; +import { TPromise } from 'vs/base/common/winjs.base'; +import { createDecorator, ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation'; export const IRequestService = createDecorator('requestService'); @@ -17,5 +17,5 @@ export interface IRequestService { * Wraps the call into WinJS.XHR to allow for mocking and telemetry. Use this instead * of calling WinJS.XHR directly. */ - makeRequest(options: http.IXHROptions): winjs.TPromise; + makeRequest(options: http.IXHROptions): TPromise; } \ No newline at end of file diff --git a/src/vs/platform/request/node/nodeRequestService.ts b/src/vs/platform/request/node/nodeRequestService.ts new file mode 100644 index 00000000000..dfceb3a6a63 --- /dev/null +++ b/src/vs/platform/request/node/nodeRequestService.ts @@ -0,0 +1,123 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import { TPromise, xhr } from 'vs/base/common/winjs.base'; +import { IDisposable, dispose } from 'vs/base/common/lifecycle'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { IRequestService } from 'vs/platform/request/common/request'; +import { assign } from 'vs/base/common/objects'; +import { IXHROptions, IXHRResponse } from 'vs/base/common/http'; +import { request } from 'vs/base/node/request'; +import { getProxyAgent } from 'vs/base/node/proxy'; +import { createGunzip } from 'zlib'; +import { Stream } from 'stream'; + +interface IHTTPConfiguration { + http?: { + proxy?: string; + proxyStrictSSL?: boolean; + }; +} + +/** + * TODO@joao: this is sort of duplicate to the existing request services... + * we need to compose, not extend!! + */ +export class NodeRequestService implements IRequestService { + + serviceId = IRequestService; + + private disposables: IDisposable[]; + private proxyUrl: string = null; + private strictSSL: boolean = true; + + constructor( + @IConfigurationService configurationService: IConfigurationService + ) { + this.disposables = []; + + const config = configurationService.getConfiguration(); + this.configure(config); + + const disposable = configurationService.onDidUpdateConfiguration(e => this.configure(e.config)); + this.disposables.push(disposable); + } + + private configure(config: IHTTPConfiguration) { + this.proxyUrl = config.http && config.http.proxy; + this.strictSSL = config.http && config.http.proxyStrictSSL; + } + + makeRequest(options: IXHROptions): TPromise { + let url = options.url; + if (!url) { + throw new Error('IRequestService.makeRequest: Url is required.'); + } + + const { proxyUrl, strictSSL } = this; + const agent = getProxyAgent(options.url, { proxyUrl, strictSSL }); + options = assign({}, options); + options = assign(options, { agent, strictSSL }); + + return request(options).then(result => new TPromise((c, e, p) => { + const res = result.res; + let stream: Stream = res; + + if (res.headers['content-encoding'] === 'gzip') { + stream = stream.pipe(createGunzip()); + } + + const data: string[] = []; + stream.on('data', c => data.push(c)); + stream.on('end', () => { + const status = res.statusCode; + + if (options.followRedirects > 0 && (status >= 300 && status <= 303 || status === 307)) { + let location = res.headers['location']; + if (location) { + let newOptions = { + type: options.type, url: location, user: options.user, password: options.password, responseType: options.responseType, headers: options.headers, + timeout: options.timeout, followRedirects: options.followRedirects - 1, data: options.data + }; + xhr(newOptions).done(c, e, p); + return; + } + } + + const response: IXHRResponse = { + responseText: data.join(''), + status, + getResponseHeader: header => res.headers[header], + readyState: 4 + }; + + if ((status >= 200 && status < 300) || status === 1223) { + c(response); + } else { + e(response); + } + }); + }, err => { + let message: string; + + if (agent) { + message = 'Unable to to connect to ' + options.url + ' through a proxy . Error: ' + err.message; + } else { + message = 'Unable to to connect to ' + options.url + '. Error: ' + err.message; + } + + return TPromise.wrapError({ + responseText: message, + status: 404 + }); + })); + } + + dispose(): void { + this.disposables = dispose(this.disposables); + } +} From 4f4ebc6b82ba964c7ccacb9b030125c929bce833 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Wed, 4 May 2016 16:45:30 +0200 Subject: [PATCH 059/297] NodeConfigurationService --- .../node/nodeConfigurationService.ts | 109 ++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 src/vs/platform/configuration/node/nodeConfigurationService.ts diff --git a/src/vs/platform/configuration/node/nodeConfigurationService.ts b/src/vs/platform/configuration/node/nodeConfigurationService.ts new file mode 100644 index 00000000000..6279a80fb6c --- /dev/null +++ b/src/vs/platform/configuration/node/nodeConfigurationService.ts @@ -0,0 +1,109 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +import { watch, FSWatcher, readFileSync } from 'fs'; +import * as path from 'path'; +import { TPromise } from 'vs/base/common/winjs.base'; +import { Delayer } from 'vs/base/common/async'; +import * as json from 'vs/base/common/json'; +import { IDisposable, dispose, toDisposable } from 'vs/base/common/lifecycle'; +import { IConfigurationService, IConfigurationServiceEvent } from 'vs/platform/configuration/common/configuration'; +import Event, {Emitter} from 'vs/base/common/event'; +import { IEnvironmentService } from 'vs/platform/environment/common/environment'; + +/** + * Configuration service to be used in the node side. + * TODO@Joao: + * - defaults handling + * - async reading + * + * At some point, an async get() on the configuration service would be + * much easier to implement and reason about. IConfigurationService2? + */ +export class NodeConfigurationService implements IConfigurationService, IDisposable { + + serviceId = IConfigurationService; + + private configurationPath: string; + private watcher: FSWatcher; + private cache: any; + private delayer: Delayer; + private disposables: IDisposable[]; + + private _onDidUpdateConfiguration = new Emitter(); + get onDidUpdateConfiguration(): Event { return this._onDidUpdateConfiguration.event; } + + constructor( + @IEnvironmentService environmentService: IEnvironmentService + ) { + this.cache = {}; + this.disposables = []; + + this.delayer = new Delayer(300); + + // TODO@joao cleanup! + this.configurationPath = path.join(environmentService.userDataPath, 'User', 'settings.json'); + + // TODO@joao sync? + this.load(); + + this.watcher = watch(path.dirname(this.configurationPath)); + this.disposables.push(toDisposable(() => { + this.watcher.removeAllListeners(); + this.watcher.close(); + })); + + this.watcher.on('change', () => this.delayer.trigger(() => this.load())); + } + + getConfiguration(section?: string): T { + return this._getConfiguration(section); + } + + loadConfiguration(section?: string): TPromise { + return TPromise.wrapError(new Error('not implemented')); + } + + private _getConfiguration(section: string = ''): T { + let value = this.cache; + + let parts = section + .split('.') + .filter(p => !!p); + + while (parts.length && value) { + let part = parts.shift(); + value = value[part]; + } + + return value; + } + + private load(): void { + let content = '{}'; + + try { + // TODO@Joao: is sync really the way to go? + content = readFileSync(this.configurationPath, 'utf8'); + } catch (error) { + content = '{}'; + } + + try { + this.cache = json.parse(content) || {}; + } catch (error) { + // noop + } + } + + hasWorkspaceConfiguration(): boolean { + return false; + } + + dispose(): void { + this.disposables = dispose(this.disposables); + } +} From eab9ef45a4974104774f549f6e2230a6856be95f Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Wed, 4 May 2016 17:04:11 +0200 Subject: [PATCH 060/297] --list-extensions #691 --- src/vs/code/buildfile.js | 1 + src/vs/code/node/argv.ts | 7 ++-- src/vs/code/node/cli.ts | 30 ++++++++++++---- src/vs/code/node/cliProcessMain.ts | 56 ++++++++++++++++++++++++++++++ 4 files changed, 85 insertions(+), 9 deletions(-) create mode 100644 src/vs/code/node/cliProcessMain.ts diff --git a/src/vs/code/buildfile.js b/src/vs/code/buildfile.js index e2f72b52dda..d722dc5e6fa 100644 --- a/src/vs/code/buildfile.js +++ b/src/vs/code/buildfile.js @@ -19,6 +19,7 @@ exports.collectModules= function() { return [ createModuleDescription('vs/code/electron-main/main', []), createModuleDescription('vs/code/node/cli', []), + createModuleDescription('vs/code/node/cliProcessMain', ['vs/code/node/cli']), createModuleDescription('vs/code/node/sharedProcessMain', []) ]; }; \ No newline at end of file diff --git a/src/vs/code/node/argv.ts b/src/vs/code/node/argv.ts index bb63f21e289..eafcac27695 100644 --- a/src/vs/code/node/argv.ts +++ b/src/vs/code/node/argv.ts @@ -28,6 +28,7 @@ export interface ParsedArgs extends minimist.ParsedArgs { timestamp: string; debugBrkPluginHost: string; debugPluginHost: string; + 'list-extensions': boolean; } const options: minimist.Opts = { @@ -50,7 +51,8 @@ const options: minimist.Opts = { 'performance', 'verbose', 'logExtensionHostCommunication', - 'disable-extensions' + 'disable-extensions', + 'list-extensions' ], alias: { help: 'h', @@ -89,4 +91,5 @@ ${ indent } window. ${ indent }--user-data-dir Specifies the directory that user data is kept in, ${ indent } useful when running as root. ${ indent }-v, --version Print version. -${ indent }-w, --wait Wait for the window to be closed before returning.`; +${ indent }-w, --wait Wait for the window to be closed before returning. +${ indent }--list-extensions List the installed extensions.`; diff --git a/src/vs/code/node/cli.ts b/src/vs/code/node/cli.ts index 86dffefb895..b11cf38726a 100644 --- a/src/vs/code/node/cli.ts +++ b/src/vs/code/node/cli.ts @@ -4,17 +4,29 @@ *--------------------------------------------------------------------------------------------*/ import { spawn } from 'child_process'; +import { TPromise } from 'vs/base/common/winjs.base'; import { assign } from 'vs/base/common/objects'; -import { parseArgs, helpMessage } from 'vs/code/node/argv'; -import pkg from 'vs/code/node/package'; +import { parseArgs, helpMessage, ParsedArgs } from 'vs/code/node/argv'; +import pkg from 'vs/platform/package'; -export function main(args: string[]) { +function shouldSpawnCliProcess(argv: ParsedArgs): boolean { + return argv['list-extensions']; +} + +interface IMainCli { + main: (argv: ParsedArgs) => TPromise; +} + +export function main(args: string[]): TPromise { const argv = parseArgs(args); if (argv.help) { console.log(helpMessage); } else if (argv.version) { console.log(pkg.version); + } else if (shouldSpawnCliProcess(argv)) { + const mainCli = new TPromise(c => require(['vs/code/node/cliProcessMain'], c)); + return mainCli.then(cli => cli.main(argv)); } else { const env = assign({}, process.env, { // this will signal Code that it was spawned from this module @@ -30,12 +42,16 @@ export function main(args: string[]) { }); if (argv.wait) { - child.on('exit', process.exit); - return; + return new TPromise(c => child.once('exit', ()=> c(null))); } } - process.exit(0); + return TPromise.as(null); } -main(process.argv.slice(2)); +main(process.argv.slice(2)) + .then(() => process.exit(0)) + .then(null, err => { + console.error(err.stack ? err.stack : err); + process.exit(1); + }); diff --git a/src/vs/code/node/cliProcessMain.ts b/src/vs/code/node/cliProcessMain.ts new file mode 100644 index 00000000000..57a2e19589c --- /dev/null +++ b/src/vs/code/node/cliProcessMain.ts @@ -0,0 +1,56 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { ParsedArgs } from 'vs/code/node/argv'; +import { TPromise } from 'vs/base/common/winjs.base'; +import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; +import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; +import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService'; +import { IEnvironmentService } from 'vs/platform/environment/common/environment'; +import { EnvironmentService } from 'vs/platform/environment/node/environmentService'; +import { IEventService } from 'vs/platform/event/common/event'; +import { EventService } from 'vs/platform/event/common/eventService'; +import { IExtensionManagementService, IExtensionGalleryService } from 'vs/platform/extensionManagement/common/extensionManagement'; +import { getExtensionId } from 'vs/platform/extensionManagement/node/extensionManagementUtil'; +import { ExtensionManagementService } from 'vs/platform/extensionManagement/node/extensionManagementService'; +import { ExtensionGalleryService } from 'vs/platform/extensionManagement/node/extensionGalleryService'; +import { ITelemetryService, NullTelemetryService } from 'vs/platform/telemetry/common/telemetry'; +import { IRequestService } from 'vs/platform/request/common/request'; +import { NodeRequestService } from 'vs/platform/request/node/nodeRequestService'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { NodeConfigurationService } from 'vs/platform/configuration/node/nodeConfigurationService'; + +class Main { + + constructor( + @IExtensionManagementService private extensionManagementService: IExtensionManagementService, + @IExtensionGalleryService private extensionGalleryService: IExtensionGalleryService + ) {} + + run(argv: ParsedArgs): TPromise { + if (argv['list-extensions']) { + return this.extensionManagementService.getInstalled().then(extensions => { + extensions.forEach(e => console.log(`${ e.displayName } (${ getExtensionId(e) })`)); + }); + } + } +} + +export function main(argv: ParsedArgs): TPromise { + const services = new ServiceCollection(); + + services.set(IEventService, new SyncDescriptor(EventService)); + services.set(IEnvironmentService, new SyncDescriptor(EnvironmentService)); + services.set(ITelemetryService, NullTelemetryService); + services.set(IConfigurationService, new SyncDescriptor(NodeConfigurationService)); + services.set(IRequestService, new SyncDescriptor(NodeRequestService)); + services.set(IExtensionManagementService, new SyncDescriptor(ExtensionManagementService)); + services.set(IExtensionGalleryService, new SyncDescriptor(ExtensionGalleryService)); + + const instantiationService: IInstantiationService = new InstantiationService(services); + const main = instantiationService.createInstance(Main); + return main.run(argv); +} From 6043ff88dc3ae1f265c3c0a998209d7d3ca620a8 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Wed, 4 May 2016 17:25:16 +0200 Subject: [PATCH 061/297] --install-extension #691 --- src/vs/code/node/argv.ts | 4 ++- src/vs/code/node/cli.ts | 2 +- src/vs/code/node/cliProcessMain.ts | 46 ++++++++++++++++++++++++++++-- 3 files changed, 47 insertions(+), 5 deletions(-) diff --git a/src/vs/code/node/argv.ts b/src/vs/code/node/argv.ts index eafcac27695..87305e387b8 100644 --- a/src/vs/code/node/argv.ts +++ b/src/vs/code/node/argv.ts @@ -29,6 +29,7 @@ export interface ParsedArgs extends minimist.ParsedArgs { debugBrkPluginHost: string; debugPluginHost: string; 'list-extensions': boolean; + 'install-extension': string; } const options: minimist.Opts = { @@ -38,7 +39,8 @@ const options: minimist.Opts = { 'extensionHomePath', 'extensionDevelopmentPath', 'extensionTestsPath', - 'timestamp' + 'timestamp', + 'install-extension' ], boolean: [ 'help', diff --git a/src/vs/code/node/cli.ts b/src/vs/code/node/cli.ts index b11cf38726a..8b301deca9b 100644 --- a/src/vs/code/node/cli.ts +++ b/src/vs/code/node/cli.ts @@ -10,7 +10,7 @@ import { parseArgs, helpMessage, ParsedArgs } from 'vs/code/node/argv'; import pkg from 'vs/platform/package'; function shouldSpawnCliProcess(argv: ParsedArgs): boolean { - return argv['list-extensions']; + return argv['list-extensions'] || !!argv['install-extension']; } interface IMainCli { diff --git a/src/vs/code/node/cliProcessMain.ts b/src/vs/code/node/cliProcessMain.ts index 57a2e19589c..875be594b1a 100644 --- a/src/vs/code/node/cliProcessMain.ts +++ b/src/vs/code/node/cliProcessMain.ts @@ -3,6 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { localize } from 'vs/nls'; import { ParsedArgs } from 'vs/code/node/argv'; import { TPromise } from 'vs/base/common/winjs.base'; import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; @@ -23,6 +24,9 @@ import { NodeRequestService } from 'vs/platform/request/node/nodeRequestService' import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { NodeConfigurationService } from 'vs/platform/configuration/node/nodeConfigurationService'; +const notFound = id => localize('notFound', "Extension '{0}' not found.", id); +const useId = localize('useId', "Make sure you use the full extension id, eg: {0}", 'ms-vscode.csharp'); + class Main { constructor( @@ -31,12 +35,48 @@ class Main { ) {} run(argv: ParsedArgs): TPromise { + // TODO@joao - make this contributable + if (argv['list-extensions']) { - return this.extensionManagementService.getInstalled().then(extensions => { - extensions.forEach(e => console.log(`${ e.displayName } (${ getExtensionId(e) })`)); - }); + return this.listExtensions(); + } else if (argv['install-extension']) { + return this.installExtension(argv['install-extension']); } } + + private listExtensions(): TPromise { + return this.extensionManagementService.getInstalled().then(extensions => { + extensions.forEach(e => console.log(`${ e.displayName } (${ getExtensionId(e) })`)); + }); + } + + private installExtension(id: string): TPromise { + return this.extensionGalleryService.query({ ids: [id] }).then(result => { + const [extension] = result.firstPage; + + if (!extension) { + return TPromise.wrapError(`${ notFound(id) }\n${ useId }`); + } + + return this.extensionManagementService.getInstalled().then(installed => { + const isInstalled = installed.some(e => getExtensionId(e) === id); + + if (isInstalled) { + return TPromise.wrapError(localize('alreadyInstalled', "Extension '{0}' is already installed.", id)); + } + + console.log(localize('foundExtension', "Found '{0}' in the marketplace.", id)); + console.log(localize('installing', "Installing...")); + + return this.extensionManagementService.install(extension).then(extension => { + console.log(localize('successInstall', "Extension '{0}' v{1} was successfully installed!", + getExtensionId(extension), + extension.version + )); + }); + }); + }); + } } export function main(argv: ParsedArgs): TPromise { From ac7a5c5d9e11ea0a819c15943b9904ad071e47f9 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Wed, 4 May 2016 17:29:33 +0200 Subject: [PATCH 062/297] --uninstall-extension #691 --- src/vs/code/node/argv.ts | 4 +++- src/vs/code/node/cli.ts | 2 +- src/vs/code/node/cliProcessMain.ts | 24 ++++++++++++++++++++---- 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/src/vs/code/node/argv.ts b/src/vs/code/node/argv.ts index 87305e387b8..e58bda0cf0d 100644 --- a/src/vs/code/node/argv.ts +++ b/src/vs/code/node/argv.ts @@ -30,6 +30,7 @@ export interface ParsedArgs extends minimist.ParsedArgs { debugPluginHost: string; 'list-extensions': boolean; 'install-extension': string; + 'uninstall-extension': string; } const options: minimist.Opts = { @@ -40,7 +41,8 @@ const options: minimist.Opts = { 'extensionDevelopmentPath', 'extensionTestsPath', 'timestamp', - 'install-extension' + 'install-extension', + 'uninstall-extension' ], boolean: [ 'help', diff --git a/src/vs/code/node/cli.ts b/src/vs/code/node/cli.ts index 8b301deca9b..85a09102b76 100644 --- a/src/vs/code/node/cli.ts +++ b/src/vs/code/node/cli.ts @@ -10,7 +10,7 @@ import { parseArgs, helpMessage, ParsedArgs } from 'vs/code/node/argv'; import pkg from 'vs/platform/package'; function shouldSpawnCliProcess(argv: ParsedArgs): boolean { - return argv['list-extensions'] || !!argv['install-extension']; + return argv['list-extensions'] || !!argv['install-extension'] || !!argv['uninstall-extension']; } interface IMainCli { diff --git a/src/vs/code/node/cliProcessMain.ts b/src/vs/code/node/cliProcessMain.ts index 875be594b1a..9e96ffeee8d 100644 --- a/src/vs/code/node/cliProcessMain.ts +++ b/src/vs/code/node/cliProcessMain.ts @@ -25,6 +25,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur import { NodeConfigurationService } from 'vs/platform/configuration/node/nodeConfigurationService'; const notFound = id => localize('notFound', "Extension '{0}' not found.", id); +const notInstalled = id => localize('notInstalled', "Extension '{0}' is not installed.", id); const useId = localize('useId', "Make sure you use the full extension id, eg: {0}", 'ms-vscode.csharp'); class Main { @@ -41,6 +42,8 @@ class Main { return this.listExtensions(); } else if (argv['install-extension']) { return this.installExtension(argv['install-extension']); + } else if (argv['uninstall-extension']) { + return this.uninstallExtension(argv['uninstall-extension']); } } @@ -69,14 +72,27 @@ class Main { console.log(localize('installing', "Installing...")); return this.extensionManagementService.install(extension).then(extension => { - console.log(localize('successInstall', "Extension '{0}' v{1} was successfully installed!", - getExtensionId(extension), - extension.version - )); + console.log(localize('successInstall', "Extension '{0}' v{1} was successfully installed!", id, extension.version)); }); }); }); } + + private uninstallExtension(id: string): TPromise { + return this.extensionManagementService.getInstalled().then(installed => { + const [extension] = installed.filter(e => getExtensionId(e) === id); + + if (!extension) { + return TPromise.wrapError(`${ notInstalled(id) }\n${ useId }`); + } + + console.log(localize('uninstalling', "Uninstalling {0}...", id)); + + return this.extensionManagementService.uninstall(extension).then(() => { + console.log(localize('successUninstall', "Extension '{0}' was successfully uninstalled!", id)); + }); + }); + } } export function main(argv: ParsedArgs): TPromise { From 93eb84884605ee8d54d2f6ed892a4d55af80263f Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Wed, 4 May 2016 17:36:17 +0200 Subject: [PATCH 063/297] (un)install multiple extensions at once fixes #691 --- src/vs/code/node/argv.ts | 4 +- src/vs/code/node/cliProcessMain.ts | 69 +++++++++++++++++------------- 2 files changed, 41 insertions(+), 32 deletions(-) diff --git a/src/vs/code/node/argv.ts b/src/vs/code/node/argv.ts index e58bda0cf0d..b595897be82 100644 --- a/src/vs/code/node/argv.ts +++ b/src/vs/code/node/argv.ts @@ -29,8 +29,8 @@ export interface ParsedArgs extends minimist.ParsedArgs { debugBrkPluginHost: string; debugPluginHost: string; 'list-extensions': boolean; - 'install-extension': string; - 'uninstall-extension': string; + 'install-extension': string | string[]; + 'uninstall-extension': string | string[]; } const options: minimist.Opts = { diff --git a/src/vs/code/node/cliProcessMain.ts b/src/vs/code/node/cliProcessMain.ts index 9e96ffeee8d..c98f1167632 100644 --- a/src/vs/code/node/cliProcessMain.ts +++ b/src/vs/code/node/cliProcessMain.ts @@ -6,6 +6,7 @@ import { localize } from 'vs/nls'; import { ParsedArgs } from 'vs/code/node/argv'; import { TPromise } from 'vs/base/common/winjs.base'; +import { sequence } from 'vs/base/common/async'; import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; @@ -41,57 +42,65 @@ class Main { if (argv['list-extensions']) { return this.listExtensions(); } else if (argv['install-extension']) { - return this.installExtension(argv['install-extension']); + const arg = argv['install-extension']; + const ids: string[] = typeof arg === 'string' ? [arg] : arg; + return this.installExtension(ids); } else if (argv['uninstall-extension']) { - return this.uninstallExtension(argv['uninstall-extension']); + const arg = argv['uninstall-extension']; + const ids: string[] = typeof arg === 'string' ? [arg] : arg; + return this.uninstallExtension(ids); } } private listExtensions(): TPromise { return this.extensionManagementService.getInstalled().then(extensions => { - extensions.forEach(e => console.log(`${ e.displayName } (${ getExtensionId(e) })`)); + extensions.forEach(e => console.log(getExtensionId(e))); }); } - private installExtension(id: string): TPromise { - return this.extensionGalleryService.query({ ids: [id] }).then(result => { - const [extension] = result.firstPage; + private installExtension(ids: string[]): TPromise { + return sequence(ids.map(id => () => { + return this.extensionGalleryService.query({ ids: [id] }).then(result => { + const [extension] = result.firstPage; - if (!extension) { - return TPromise.wrapError(`${ notFound(id) }\n${ useId }`); - } - - return this.extensionManagementService.getInstalled().then(installed => { - const isInstalled = installed.some(e => getExtensionId(e) === id); - - if (isInstalled) { - return TPromise.wrapError(localize('alreadyInstalled', "Extension '{0}' is already installed.", id)); + if (!extension) { + return TPromise.wrapError(`${ notFound(id) }\n${ useId }`); } - console.log(localize('foundExtension', "Found '{0}' in the marketplace.", id)); - console.log(localize('installing', "Installing...")); + return this.extensionManagementService.getInstalled().then(installed => { + const isInstalled = installed.some(e => getExtensionId(e) === id); - return this.extensionManagementService.install(extension).then(extension => { - console.log(localize('successInstall', "Extension '{0}' v{1} was successfully installed!", id, extension.version)); + if (isInstalled) { + return TPromise.wrapError(localize('alreadyInstalled', "Extension '{0}' is already installed.", id)); + } + + console.log(localize('foundExtension', "Found '{0}' in the marketplace.", id)); + console.log(localize('installing', "Installing...")); + + return this.extensionManagementService.install(extension).then(extension => { + console.log(localize('successInstall', "Extension '{0}' v{1} was successfully installed!", id, extension.version)); + }); }); }); - }); + })); } - private uninstallExtension(id: string): TPromise { - return this.extensionManagementService.getInstalled().then(installed => { - const [extension] = installed.filter(e => getExtensionId(e) === id); + private uninstallExtension(ids: string[]): TPromise { + return sequence(ids.map(id => () => { + return this.extensionManagementService.getInstalled().then(installed => { + const [extension] = installed.filter(e => getExtensionId(e) === id); - if (!extension) { - return TPromise.wrapError(`${ notInstalled(id) }\n${ useId }`); - } + if (!extension) { + return TPromise.wrapError(`${ notInstalled(id) }\n${ useId }`); + } - console.log(localize('uninstalling', "Uninstalling {0}...", id)); + console.log(localize('uninstalling', "Uninstalling {0}...", id)); - return this.extensionManagementService.uninstall(extension).then(() => { - console.log(localize('successUninstall', "Extension '{0}' was successfully uninstalled!", id)); + return this.extensionManagementService.uninstall(extension).then(() => { + console.log(localize('successUninstall', "Extension '{0}' was successfully uninstalled!", id)); + }); }); - }); + })); } } From b455db9f356a9e395aefa44d9b3f5597c67b7aa0 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Wed, 4 May 2016 17:40:46 +0200 Subject: [PATCH 064/297] docs --- src/vs/code/node/argv.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/vs/code/node/argv.ts b/src/vs/code/node/argv.ts index b595897be82..49121642375 100644 --- a/src/vs/code/node/argv.ts +++ b/src/vs/code/node/argv.ts @@ -96,4 +96,8 @@ ${ indent }--user-data-dir Specifies the directory that user data is kept ${ indent } useful when running as root. ${ indent }-v, --version Print version. ${ indent }-w, --wait Wait for the window to be closed before returning. -${ indent }--list-extensions List the installed extensions.`; +${ indent }--list-extensions List the installed extensions. +${ indent }--install-extension +${ indent } Installs an extension. +${ indent }--list-extensions +${ indent } Uninstalls an extension.`; From fc90ee73a59a43bd9734b0a8f19c41dcd5bc0099 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Wed, 4 May 2016 17:41:18 +0200 Subject: [PATCH 065/297] fix compile error --- src/vs/workbench/parts/debug/node/rawDebugSession.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/parts/debug/node/rawDebugSession.ts b/src/vs/workbench/parts/debug/node/rawDebugSession.ts index 7fd9d3d8ef0..3032ca03445 100644 --- a/src/vs/workbench/parts/debug/node/rawDebugSession.ts +++ b/src/vs/workbench/parts/debug/node/rawDebugSession.ts @@ -21,7 +21,7 @@ import debug = require('vs/workbench/parts/debug/common/debug'); import { Adapter } from 'vs/workbench/parts/debug/node/debugAdapter'; import v8 = require('vs/workbench/parts/debug/node/v8Protocol'); import { IOutputService } from 'vs/workbench/parts/output/common/output'; -import { ExtensionsChannelId } from 'vs/workbench/parts/extensions/common/extensions'; +import { ExtensionsChannelId } from 'vs/platform/extensionManagement/common/extensionManagement'; import { shell } from 'electron'; From 4014d838181ff4aa03f2dffe25911f8d8c2a18e3 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 6 May 2016 09:13:53 +0200 Subject: [PATCH 066/297] Fixes #6149: Escape selected text used to seed search input when regex toggle is on --- .../contrib/find/common/findController.ts | 7 ++++- .../find/test/common/findController.test.ts | 30 ++++++++++++++++++- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/vs/editor/contrib/find/common/findController.ts b/src/vs/editor/contrib/find/common/findController.ts index dca8998c28b..8217c1f4fbe 100644 --- a/src/vs/editor/contrib/find/common/findController.ts +++ b/src/vs/editor/contrib/find/common/findController.ts @@ -13,6 +13,7 @@ import {Range} from 'vs/editor/common/core/range'; import {Selection} from 'vs/editor/common/core/selection'; import {EditorAction} from 'vs/editor/common/editorAction'; import {Behaviour} from 'vs/editor/common/editorActionEnablement'; +import * as strings from 'vs/base/common/strings'; import * as editorCommon from 'vs/editor/common/editorCommon'; import {CommonEditorRegistry, ContextKey, EditorActionDescriptor} from 'vs/editor/common/editorCommonExtensions'; import {FIND_IDS, FindModelBoundToEditorModel} from 'vs/editor/contrib/find/common/findModel'; @@ -161,7 +162,11 @@ export class CommonFindController extends Disposable implements editorCommon.IEd if (opts.seedSearchStringFromSelection) { let selectionSearchString = this.getSelectionSearchString(); if (selectionSearchString) { - stateChanges.searchString = selectionSearchString; + if (this._state.isRegex) { + stateChanges.searchString = strings.escapeRegExpCharacters(selectionSearchString); + } else { + stateChanges.searchString = selectionSearchString; + } } } diff --git a/src/vs/editor/contrib/find/test/common/findController.test.ts b/src/vs/editor/contrib/find/test/common/findController.test.ts index 084602eb991..327b34a49c9 100644 --- a/src/vs/editor/contrib/find/test/common/findController.test.ts +++ b/src/vs/editor/contrib/find/test/common/findController.test.ts @@ -7,6 +7,7 @@ import * as assert from 'assert'; import {EditOperation} from 'vs/editor/common/core/editOperation'; import {Position} from 'vs/editor/common/core/position'; +import {Selection} from 'vs/editor/common/core/selection'; import {Range} from 'vs/editor/common/core/range'; import {IRange} from 'vs/editor/common/editorCommon'; import {CommonFindController, FindStartFocusAction, IFindStartOptions, NextMatchFindAction, StartFindAction} from 'vs/editor/contrib/find/common/findController'; @@ -94,7 +95,6 @@ suite('FindController', () => { 'import nls = require(\'vs/nls\');' ], {}, (editor, cursor) => { - // The cursor is at the very top, of the file, at the first ABC let findController = editor.registerAndInstantiateContribution(TestFindController); let nextMatchFindAction = new NextMatchFindAction({id:'',label:''}, editor); @@ -113,4 +113,32 @@ suite('FindController', () => { nextMatchFindAction.dispose(); }); }); + + test('issue #6149: Auto-escape highlighted text for search and replace regex mode', () => { + withMockCodeEditor([ + 'var x = (3 * 5)', + 'var y = (3 * 5)', + 'var z = (3 * 5)', + ], {}, (editor, cursor) => { + + let findController = editor.registerAndInstantiateContribution(TestFindController); + let startFindAction = new StartFindAction({id:'',label:''}, editor); + let nextMatchFindAction = new NextMatchFindAction({id:'',label:''}, editor); + + editor.setSelection(new Selection(1, 9, 1, 13)); + + findController.toggleRegex(); + startFindAction.run(); + + nextMatchFindAction.run(); + assert.deepEqual(fromRange(editor.getSelection()), [2, 9, 2, 13]); + + nextMatchFindAction.run(); + assert.deepEqual(fromRange(editor.getSelection()), [1, 9, 1, 13]); + + findController.dispose(); + startFindAction.dispose(); + nextMatchFindAction.dispose(); + }); + }); }); From 68fc6edf095ee0a55f2fc71ab37f4e8387c82d2b Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 6 May 2016 09:21:52 +0200 Subject: [PATCH 067/297] Fixes #6147: Set editor font info on inline diff view zones --- src/vs/editor/browser/widget/diffEditorWidget.ts | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/vs/editor/browser/widget/diffEditorWidget.ts b/src/vs/editor/browser/widget/diffEditorWidget.ts index 59b579e3a9b..def99b7dcd6 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget.ts @@ -24,6 +24,7 @@ import {renderLine, RenderLineInput} from 'vs/editor/common/viewLayout/viewLineR import * as editorBrowser from 'vs/editor/browser/editorBrowser'; import {CodeEditorWidget} from 'vs/editor/browser/widget/codeEditorWidget'; import {ViewLineToken, ViewLineTokens} from 'vs/editor/common/core/viewLineToken'; +import {Configuration} from 'vs/editor/browser/config/configuration'; interface IEditorScrollEvent { scrollLeft: number; @@ -1109,7 +1110,7 @@ class ForeignViewZonesIterator { } } -class ViewZonesComputer { +abstract class ViewZonesComputer { private lineChanges:editorCommon.ILineChange[]; private originalForeignVZ:editorCommon.IEditorWhitespace[]; @@ -1301,13 +1302,9 @@ class ViewZonesComputer { return result; } - _produceOriginalFromDiff(lineChange:editorCommon.ILineChange, lineChangeOriginalLength:number, lineChangeModifiedLength:number): IMyViewZone { - throw new Error('NotImplemented'); - } + protected abstract _produceOriginalFromDiff(lineChange:editorCommon.ILineChange, lineChangeOriginalLength:number, lineChangeModifiedLength:number): IMyViewZone; - _produceModifiedFromDiff(lineChange:editorCommon.ILineChange, lineChangeOriginalLength:number, lineChangeModifiedLength:number): IMyViewZone { - throw new Error('NotImplemented'); - } + protected abstract _produceModifiedFromDiff(lineChange:editorCommon.ILineChange, lineChangeOriginalLength:number, lineChangeModifiedLength:number): IMyViewZone; } class DiffEdtorWidgetSideBySide extends DiffEditorWidgetStyle implements IDiffEditorWidgetStyle, IVerticalSashLayoutProvider { @@ -1766,6 +1763,7 @@ class InlineViewZonesComputer extends ViewZonesComputer { var domNode = document.createElement('div'); domNode.className = 'view-lines line-delete'; domNode.innerHTML = html.join(''); + Configuration.applyFontInfoSlow(domNode, this.modifiedEditorConfiguration.fontInfo); return { shouldNotShrink: true, From c92a360c4564b13ed460a9828f1c18bbfc8a3855 Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 6 May 2016 09:36:12 +0200 Subject: [PATCH 068/297] debug: add nls comments fixes #6124 --- src/vs/workbench/parts/debug/browser/debugViews.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/parts/debug/browser/debugViews.ts b/src/vs/workbench/parts/debug/browser/debugViews.ts index 793e6c74aed..f86536cfb6c 100644 --- a/src/vs/workbench/parts/debug/browser/debugViews.ts +++ b/src/vs/workbench/parts/debug/browser/debugViews.ts @@ -151,7 +151,7 @@ export class WatchExpressionsView extends viewlet.CollapsibleViewletView { renderer: this.instantiationService.createInstance(viewer.WatchExpressionsRenderer, actionProvider, this.actionRunner), accessibilityProvider: new viewer.WatchExpressionsAccessibilityProvider(), controller: new viewer.WatchExpressionsController(this.debugService, this.contextMenuService, actionProvider) - }, debugTreeOptions(nls.localize('watchAriaTreeLabel', "Debug Watch Expressions"))); + }, debugTreeOptions(nls.localize({ comment: ['Debug is a noun in this context, not a verb.'], key: 'watchAriaTreeLabel'}, "Debug Watch Expressions"))); this.tree.setInput(this.debugService.getModel()); @@ -225,7 +225,7 @@ export class CallStackView extends viewlet.CollapsibleViewletView { renderer: this.instantiationService.createInstance(viewer.CallStackRenderer), accessibilityProvider: this.instantiationService.createInstance(viewer.CallstackAccessibilityProvider), controller: new viewer.BaseDebugController(this.debugService, this.contextMenuService, actionProvider) - }, debugTreeOptions(nls.localize('callStackAriaLabel', "Debug Call Stack"))); + }, debugTreeOptions(nls.localize({ comment: ['Debug is a noun in this context, not a verb.'], key: 'callStackAriaLabel'}, "Debug Call Stack"))); this.toDispose.push(this.tree.addListener2('selection', (e: tree.ISelectionEvent) => { if (!e.selection.length || !e.payload) { @@ -380,7 +380,7 @@ export class BreakpointsView extends viewlet.AdaptiveCollapsibleViewletView { return first.desiredLineNumber - second.desiredLineNumber; } } - }, debugTreeOptions(nls.localize('breakpointsAriaTreeLabel', "Debug Breakpoints"))); + }, debugTreeOptions(nls.localize({ comment: ['Debug is a noun in this context, not a verb.'], key: 'breakpointsAriaTreeLabel'}, "Debug Breakpoints"))); const debugModel = this.debugService.getModel(); From 57c258e9c9d626acb28bf81e923771114ff5b056 Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 6 May 2016 10:21:01 +0200 Subject: [PATCH 069/297] debug: null guard --- src/vs/workbench/parts/debug/electron-browser/debugService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/parts/debug/electron-browser/debugService.ts b/src/vs/workbench/parts/debug/electron-browser/debugService.ts index fb3927b1758..bf52dd6d8e9 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugService.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugService.ts @@ -862,7 +862,7 @@ export class DebugService implements debug.IDebugService { if (!cancelTransitionToRunningState) { aria.status(nls.localize('debuggingContinued', "Debugging continued.")); // TODO@Isidor temporary workaround for #5835 - if (strings.equalsIgnoreCase(this.session.configuration.type, 'go')) { + if (this.session && strings.equalsIgnoreCase(this.session.configuration.type, 'go')) { this.model.clearThreads(false); } else { this.model.clearThreads(false, threadId); From 90b959c16de2efe2d8b88e132fca125a3cc8e67a Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 6 May 2016 10:24:21 +0200 Subject: [PATCH 070/297] debug: do not auto focus editor on session end fixes #6088 --- src/vs/workbench/parts/debug/electron-browser/debugService.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/vs/workbench/parts/debug/electron-browser/debugService.ts b/src/vs/workbench/parts/debug/electron-browser/debugService.ts index bf52dd6d8e9..fc131aa3836 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugService.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugService.ts @@ -703,7 +703,6 @@ export class DebugService implements debug.IDebugService { } this.partService.removeClass('debugging'); - this.editorService.focusEditor(); this.model.clearThreads(true); this.setFocusedStackFrameAndEvaluate(null).done(null, errors.onUnexpectedError); From ef28669e2ba20212912638798a124f63e093b48b Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 6 May 2016 10:32:39 +0200 Subject: [PATCH 071/297] expose isOptedIn flag, #6097 --- src/vs/platform/telemetry/browser/telemetryService.ts | 4 ++++ src/vs/platform/telemetry/common/remoteTelemetryService.ts | 4 ++++ src/vs/platform/telemetry/common/telemetry.ts | 3 +++ 3 files changed, 11 insertions(+) diff --git a/src/vs/platform/telemetry/browser/telemetryService.ts b/src/vs/platform/telemetry/browser/telemetryService.ts index eb3e857c371..d59020085e3 100644 --- a/src/vs/platform/telemetry/browser/telemetryService.ts +++ b/src/vs/platform/telemetry/browser/telemetryService.ts @@ -114,6 +114,10 @@ export class TelemetryService implements ITelemetryService { } } + get isOptedIn(): boolean { + return this._configuration.userOptIn; + } + public getTelemetryInfo(): TPromise { return TPromise.as(this._telemetryInfo); } diff --git a/src/vs/platform/telemetry/common/remoteTelemetryService.ts b/src/vs/platform/telemetry/common/remoteTelemetryService.ts index dc4c293b5fa..a13d90c54e0 100644 --- a/src/vs/platform/telemetry/common/remoteTelemetryService.ts +++ b/src/vs/platform/telemetry/common/remoteTelemetryService.ts @@ -42,6 +42,10 @@ export class RemoteTelemetryService implements ITelemetryService { this._proxy = threadService.getRemotable(RemoteTelemetryServiceHelper); } + get isOptedIn(): boolean { + throw notImplemented(); + } + getTelemetryInfo(): TPromise { return this._proxy.$getTelemetryInfo(); } diff --git a/src/vs/platform/telemetry/common/telemetry.ts b/src/vs/platform/telemetry/common/telemetry.ts index 07bce6ae71f..6131d8b9646 100644 --- a/src/vs/platform/telemetry/common/telemetry.ts +++ b/src/vs/platform/telemetry/common/telemetry.ts @@ -33,6 +33,8 @@ export interface ITelemetryService { getTelemetryInfo(): TPromise; + isOptedIn: boolean; + addTelemetryAppender(appender: ITelemetryAppender): IDisposable; } @@ -66,6 +68,7 @@ export const NullTelemetryService: ITelemetryService = { timedPublicLog(name: string, data?: any): ITimerEvent { return nullEvent; }, publicLog(eventName: string, data?: any): void { }, addTelemetryAppender(appender): IDisposable { return { dispose() { } }; }, + isOptedIn: true, getTelemetryInfo(): TPromise { return TPromise.as({ instanceId: 'someValue.instanceId', From bf0fc83e3b636e99350552b35a300c12ba18a21b Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 6 May 2016 10:39:48 +0200 Subject: [PATCH 072/297] fixes #6097 --- src/vs/workbench/parts/debug/electron-browser/debugService.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/parts/debug/electron-browser/debugService.ts b/src/vs/workbench/parts/debug/electron-browser/debugService.ts index fc131aa3836..3f1725954c5 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugService.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugService.ts @@ -289,7 +289,8 @@ export class DebugService implements debug.IDebugService { this.toDisposeOnSessionEnd.push(this.session.onDidOutput(event => { if (event.body && event.body.category === 'telemetry') { // only log telemetry events from debug adapter if the adapter provided the telemetry key - if (this.telemetryAdapter) { + // and the user opted in telemetry + if (this.telemetryAdapter && this.telemetryService.isOptedIn) { this.telemetryAdapter.log(event.body.output, event.body.data); } } else if (event.body && typeof event.body.output === 'string' && event.body.output.length > 0) { From e30a6debf3ea9f383f5cae3db744feb8b7561b8e Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 6 May 2016 10:39:57 +0200 Subject: [PATCH 073/297] debt - remove used service dependency --- src/vs/platform/extensions/common/nativeExtensionService.ts | 5 +---- src/vs/workbench/electron-browser/shell.ts | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/vs/platform/extensions/common/nativeExtensionService.ts b/src/vs/platform/extensions/common/nativeExtensionService.ts index b5c9100e071..1ec4c63944a 100644 --- a/src/vs/platform/extensions/common/nativeExtensionService.ts +++ b/src/vs/platform/extensions/common/nativeExtensionService.ts @@ -48,7 +48,6 @@ export class MainProcessExtensionService extends AbstractExtensionService Date: Fri, 6 May 2016 11:08:31 +0200 Subject: [PATCH 074/297] Prepare for mutating `canUseTranslate3d` at runtime --- src/vs/base/browser/ui/list/listView.ts | 2 +- .../browser/ui/scrollbar/abstractScrollbar.ts | 18 +++++++++-------- .../ui/scrollbar/horizontalScrollbar.ts | 7 ++++--- .../browser/ui/scrollbar/scrollableElement.ts | 8 ++++---- .../ui/scrollbar/scrollableElementOptions.ts | 12 ++++++++--- .../browser/ui/scrollbar/verticalScrollbar.ts | 7 ++++--- src/vs/base/parts/tree/browser/treeView.ts | 2 +- src/vs/editor/browser/view/viewOverlays.ts | 2 ++ .../browser/viewLayout/scrollManager.ts | 10 ++++++++-- .../browser/viewParts/lines/viewLines.ts | 5 ++++- .../overviewRuler/overviewRulerImpl.ts | 8 +++++--- .../viewParts/viewCursors/viewCursors.ts | 20 +++++++++++-------- .../contrib/suggest/browser/suggestWidget.ts | 2 +- .../browser/parts/editor/binaryDiffEditor.ts | 4 ++-- 14 files changed, 67 insertions(+), 40 deletions(-) diff --git a/src/vs/base/browser/ui/list/listView.ts b/src/vs/base/browser/ui/list/listView.ts index 6a4dc72ed09..ff584114ea9 100644 --- a/src/vs/base/browser/ui/list/listView.ts +++ b/src/vs/base/browser/ui/list/listView.ts @@ -87,7 +87,7 @@ export class ListView implements IDisposable { this.gesture = new Gesture(this.rowsContainer); this.scrollableElement = new ScrollableElement(this.rowsContainer, { - forbidTranslate3dUse: true, + canUseTranslate3d: false, horizontal: 'hidden', vertical: 'auto', useShadows: false, diff --git a/src/vs/base/browser/ui/scrollbar/abstractScrollbar.ts b/src/vs/base/browser/ui/scrollbar/abstractScrollbar.ts index c3e625b85f0..c5b108a3f1c 100644 --- a/src/vs/base/browser/ui/scrollbar/abstractScrollbar.ts +++ b/src/vs/base/browser/ui/scrollbar/abstractScrollbar.ts @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import * as Browser from 'vs/base/browser/browser'; import * as Platform from 'vs/base/common/platform'; import * as DomUtils from 'vs/base/browser/dom'; import {IMouseEvent, StandardMouseEvent, StandardMouseWheelEvent} from 'vs/base/browser/mouseEvent'; @@ -34,7 +33,7 @@ export interface ScrollbarHost { } export interface AbstractScrollbarOptions { - forbidTranslate3dUse: boolean; + canUseTranslate3d: boolean; lazyRender:boolean; host: ScrollbarHost; scrollbarState: ScrollbarState; @@ -45,7 +44,7 @@ export interface AbstractScrollbarOptions { export abstract class AbstractScrollbar extends Widget { - protected _forbidTranslate3dUse: boolean; + protected _canUseTranslate3d: boolean; protected _host: ScrollbarHost; protected _scrollable: Scrollable; private _lazyRender: boolean; @@ -60,7 +59,7 @@ export abstract class AbstractScrollbar extends Widget { constructor(opts:AbstractScrollbarOptions) { super(); - this._forbidTranslate3dUse = opts.forbidTranslate3dUse; + this._canUseTranslate3d = opts.canUseTranslate3d; this._lazyRender = opts.lazyRender; this._host = opts.host; this._scrollable = opts.scrollable; @@ -69,10 +68,6 @@ export abstract class AbstractScrollbar extends Widget { this._mouseMoveMonitor = this._register(new GlobalMouseMoveMonitor()); this._shouldRender = true; this.domNode = createFastDomNode(document.createElement('div')); - if (!this._forbidTranslate3dUse && Browser.canUseTranslate3d) { - // Put the scrollbar in its own layer - this.domNode.setTransform('translate3d(0px, 0px, 0px)'); - } this._visibilityController.setDomNode(this.domNode); this.domNode.setPosition('absolute'); @@ -159,6 +154,13 @@ export abstract class AbstractScrollbar extends Widget { } this._shouldRender = false; + if (this._canUseTranslate3d) { + // Put the scrollbar in its own layer + this.domNode.setTransform('translate3d(0px, 0px, 0px)'); + } else { + this.domNode.setTransform(''); + } + this._renderDomNode(this._scrollbarState.getRectangleLargeSize(), this._scrollbarState.getRectangleSmallSize()); this._updateSlider(this._scrollbarState.getSliderSize(), this._scrollbarState.getArrowSize() + this._scrollbarState.getSliderPosition()); } diff --git a/src/vs/base/browser/ui/scrollbar/horizontalScrollbar.ts b/src/vs/base/browser/ui/scrollbar/horizontalScrollbar.ts index abc765bf420..0481ccbefbb 100644 --- a/src/vs/base/browser/ui/scrollbar/horizontalScrollbar.ts +++ b/src/vs/base/browser/ui/scrollbar/horizontalScrollbar.ts @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import * as Browser from 'vs/base/browser/browser'; import {AbstractScrollbar, ScrollbarHost, IMouseMoveEventData} from 'vs/base/browser/ui/scrollbar/abstractScrollbar'; import {IMouseEvent, StandardMouseWheelEvent} from 'vs/base/browser/mouseEvent'; import {IDomNodePosition} from 'vs/base/browser/dom'; @@ -18,7 +17,7 @@ export class HorizontalScrollbar extends AbstractScrollbar { constructor(scrollable: Scrollable, options: ScrollableElementResolvedOptions, host: ScrollbarHost) { super({ - forbidTranslate3dUse: options.forbidTranslate3dUse, + canUseTranslate3d: options.canUseTranslate3d, lazyRender: options.lazyRender, host: host, scrollbarState: new ScrollbarState( @@ -63,9 +62,11 @@ export class HorizontalScrollbar extends AbstractScrollbar { protected _updateSlider(sliderSize: number, sliderPosition: number): void { this.slider.setWidth(sliderSize); - if (!this._forbidTranslate3dUse && Browser.canUseTranslate3d) { + if (this._canUseTranslate3d) { this.slider.setTransform('translate3d(' + sliderPosition + 'px, 0px, 0px)'); + this.slider.setLeft(0); } else { + this.slider.setTransform(''); this.slider.setLeft(sliderPosition); } } diff --git a/src/vs/base/browser/ui/scrollbar/scrollableElement.ts b/src/vs/base/browser/ui/scrollbar/scrollableElement.ts index 6b51e5bd1bc..7bbb8abf995 100644 --- a/src/vs/base/browser/ui/scrollbar/scrollableElement.ts +++ b/src/vs/base/browser/ui/scrollbar/scrollableElement.ts @@ -6,12 +6,13 @@ import 'vs/css!./media/scrollbars'; +import * as Browser from 'vs/base/browser/browser'; import * as DomUtils from 'vs/base/browser/dom'; import * as Platform from 'vs/base/common/platform'; import {StandardMouseWheelEvent, IMouseEvent} from 'vs/base/browser/mouseEvent'; import {HorizontalScrollbar} from 'vs/base/browser/ui/scrollbar/horizontalScrollbar'; import {VerticalScrollbar} from 'vs/base/browser/ui/scrollbar/verticalScrollbar'; -import {ScrollableElementCreationOptions, ScrollableElementResolvedOptions} from 'vs/base/browser/ui/scrollbar/scrollableElementOptions'; +import {ScrollableElementCreationOptions, ScrollableElementChangeOptions, ScrollableElementResolvedOptions} from 'vs/base/browser/ui/scrollbar/scrollableElementOptions'; import {visibilityFromString} from 'vs/base/browser/ui/scrollbar/scrollbarVisibilityController'; import {IDisposable, dispose} from 'vs/base/common/lifecycle'; import {Scrollable, ScrollEvent, INewScrollState} from 'vs/base/common/scrollable'; @@ -181,8 +182,7 @@ export class ScrollableElement extends Widget { * Really this is Editor.IEditorScrollbarOptions, but base shouldn't * depend on Editor. */ - public updateOptions(newOptions: ScrollableElementCreationOptions): void { - // only support handleMouseWheel changes for now + public updateOptions(newOptions: ScrollableElementChangeOptions): void { let massagedOptions = resolveOptions(newOptions); this._options.handleMouseWheel = massagedOptions.handleMouseWheel; this._options.mouseWheelScrollSensitivity = massagedOptions.mouseWheelScrollSensitivity; @@ -400,7 +400,7 @@ export class DomScrollableElement extends ScrollableElement { function resolveOptions(opts: ScrollableElementCreationOptions): ScrollableElementResolvedOptions { let result: ScrollableElementResolvedOptions = { - forbidTranslate3dUse: (typeof opts.forbidTranslate3dUse !== 'undefined' ? opts.forbidTranslate3dUse : false), + canUseTranslate3d: opts.canUseTranslate3d && Browser.canUseTranslate3d, lazyRender: (typeof opts.lazyRender !== 'undefined' ? opts.lazyRender : false), className: (typeof opts.className !== 'undefined' ? opts.className : ''), useShadows: (typeof opts.useShadows !== 'undefined' ? opts.useShadows : true), diff --git a/src/vs/base/browser/ui/scrollbar/scrollableElementOptions.ts b/src/vs/base/browser/ui/scrollbar/scrollableElementOptions.ts index 3eef4852226..28a8b53f153 100644 --- a/src/vs/base/browser/ui/scrollbar/scrollableElementOptions.ts +++ b/src/vs/base/browser/ui/scrollbar/scrollableElementOptions.ts @@ -8,9 +8,9 @@ import {Visibility} from 'vs/base/browser/ui/scrollbar/scrollbarVisibilityContro export interface ScrollableElementCreationOptions { /** - * Prevent the scrollbar rendering from using translate3d. Defaults to false. + * Allow scrollbar rendering to use translate3d. */ - forbidTranslate3dUse?: boolean; + canUseTranslate3d: boolean; /** * The scrollable element should not do any DOM mutations until renderNow() is called. * Defaults to false. @@ -98,8 +98,14 @@ export interface ScrollableElementCreationOptions { saveLastScrollTimeOnClassName?: string; } +export interface ScrollableElementChangeOptions { + canUseTranslate3d: boolean; + handleMouseWheel?: boolean; + mouseWheelScrollSensitivity?: number; +} + export interface ScrollableElementResolvedOptions { - forbidTranslate3dUse: boolean; + canUseTranslate3d: boolean; lazyRender: boolean; className: string; useShadows: boolean; diff --git a/src/vs/base/browser/ui/scrollbar/verticalScrollbar.ts b/src/vs/base/browser/ui/scrollbar/verticalScrollbar.ts index a7e91d33fc9..1f511d29172 100644 --- a/src/vs/base/browser/ui/scrollbar/verticalScrollbar.ts +++ b/src/vs/base/browser/ui/scrollbar/verticalScrollbar.ts @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import * as Browser from 'vs/base/browser/browser'; import {AbstractScrollbar, ScrollbarHost, IMouseMoveEventData} from 'vs/base/browser/ui/scrollbar/abstractScrollbar'; import {IMouseEvent, StandardMouseWheelEvent} from 'vs/base/browser/mouseEvent'; import {IDomNodePosition} from 'vs/base/browser/dom'; @@ -18,7 +17,7 @@ export class VerticalScrollbar extends AbstractScrollbar { constructor(scrollable: Scrollable, options: ScrollableElementResolvedOptions, host: ScrollbarHost) { super({ - forbidTranslate3dUse: options.forbidTranslate3dUse, + canUseTranslate3d: options.canUseTranslate3d, lazyRender: options.lazyRender, host: host, scrollbarState: new ScrollbarState( @@ -64,9 +63,11 @@ export class VerticalScrollbar extends AbstractScrollbar { protected _updateSlider(sliderSize: number, sliderPosition: number): void { this.slider.setHeight(sliderSize); - if (!this._forbidTranslate3dUse && Browser.canUseTranslate3d) { + if (this._canUseTranslate3d) { this.slider.setTransform('translate3d(0px, ' + sliderPosition + 'px, 0px)'); + this.slider.setTop(0); } else { + this.slider.setTransform(''); this.slider.setTop(sliderPosition); } } diff --git a/src/vs/base/parts/tree/browser/treeView.ts b/src/vs/base/parts/tree/browser/treeView.ts index 8cd9b64428e..60636cdcc65 100644 --- a/src/vs/base/parts/tree/browser/treeView.ts +++ b/src/vs/base/parts/tree/browser/treeView.ts @@ -487,7 +487,7 @@ export class TreeView extends HeightMap { this.wrapper = document.createElement('div'); this.wrapper.className = 'monaco-tree-wrapper'; this.scrollableElement = new ScrollableElementImpl.ScrollableElement(this.wrapper, { - forbidTranslate3dUse: true, + canUseTranslate3d: false, horizontal: 'hidden', vertical: context.options.verticalScrollMode || 'auto', useShadows: context.options.useShadows, diff --git a/src/vs/editor/browser/view/viewOverlays.ts b/src/vs/editor/browser/view/viewOverlays.ts index 0d6b883b7cb..4bc5259443f 100644 --- a/src/vs/editor/browser/view/viewOverlays.ts +++ b/src/vs/editor/browser/view/viewOverlays.ts @@ -283,7 +283,9 @@ export class MarginViewOverlays extends ViewOverlays { if (browser.canUseTranslate3d) { var transform = 'translate3d(0px, ' + ctx.linesViewportData.visibleRangesDeltaTop + 'px, 0px)'; this.domNode.setTransform(transform); + this.domNode.setTop(0); } else { + this.domNode.setTransform(''); this.domNode.setTop(ctx.linesViewportData.visibleRangesDeltaTop); } var height = Math.min(this._layoutProvider.getTotalHeight(), 1000000); diff --git a/src/vs/editor/browser/viewLayout/scrollManager.ts b/src/vs/editor/browser/viewLayout/scrollManager.ts index 31d86db6262..5dcf4b03bbf 100644 --- a/src/vs/editor/browser/viewLayout/scrollManager.ts +++ b/src/vs/editor/browser/viewLayout/scrollManager.ts @@ -6,7 +6,7 @@ import {IDisposable, dispose} from 'vs/base/common/lifecycle'; import * as dom from 'vs/base/browser/dom'; -import {ScrollableElementCreationOptions} from 'vs/base/browser/ui/scrollbar/scrollableElementOptions'; +import {ScrollableElementCreationOptions, ScrollableElementChangeOptions} from 'vs/base/browser/ui/scrollbar/scrollableElementOptions'; import {IOverviewRulerLayoutInfo, ScrollableElement} from 'vs/base/browser/ui/scrollbar/scrollableElement'; import {EventType, IConfiguration, IConfigurationChangedEvent, IScrollEvent, INewScrollPosition} from 'vs/editor/common/editorCommon'; import {ClassNames} from 'vs/editor/browser/editorBrowser'; @@ -36,6 +36,7 @@ export class ScrollManager implements IDisposable { var configScrollbarOpts = this.configuration.editor.scrollbar; var scrollbarOptions:ScrollableElementCreationOptions = { + canUseTranslate3d: true, listenOnDomNode: viewDomNode, vertical: configScrollbarOpts.vertical, horizontal: configScrollbarOpts.horizontal, @@ -64,7 +65,12 @@ export class ScrollManager implements IDisposable { this.toDispose.push(this.configuration.onDidChange((e:IConfigurationChangedEvent) => { this.scrollbar.updateClassName(this.configuration.editor.theme); if (e.scrollbar) { - this.scrollbar.updateOptions(this.configuration.editor.scrollbar); + let newOpts:ScrollableElementChangeOptions = { + canUseTranslate3d: true, + handleMouseWheel: this.configuration.editor.scrollbar.handleMouseWheel, + mouseWheelScrollSensitivity: this.configuration.editor.scrollbar.mouseWheelScrollSensitivity + }; + this.scrollbar.updateOptions(newOpts); } })); diff --git a/src/vs/editor/browser/viewParts/lines/viewLines.ts b/src/vs/editor/browser/viewParts/lines/viewLines.ts index 1fd31b5e081..d0cc972c7aa 100644 --- a/src/vs/editor/browser/viewParts/lines/viewLines.ts +++ b/src/vs/editor/browser/viewParts/lines/viewLines.ts @@ -408,9 +408,12 @@ export class ViewLines extends ViewLayer { // (4) handle scrolling if (browser.canUseTranslate3d) { - var transform = 'translate3d(' + -this._layoutProvider.getScrollLeft() + 'px, ' + linesViewportData.visibleRangesDeltaTop + 'px, 0px)'; + let transform = 'translate3d(' + -this._layoutProvider.getScrollLeft() + 'px, ' + linesViewportData.visibleRangesDeltaTop + 'px, 0px)'; StyleMutator.setTransform(this.domNode.domNode.parentNode, transform); + StyleMutator.setTop(this.domNode.domNode.parentNode, 0); // TODO@Alex + StyleMutator.setLeft(this.domNode.domNode.parentNode, 0); // TODO@Alex } else { + StyleMutator.setTransform(this.domNode.domNode.parentNode, ''); StyleMutator.setTop(this.domNode.domNode.parentNode, linesViewportData.visibleRangesDeltaTop); // TODO@Alex StyleMutator.setLeft(this.domNode.domNode.parentNode, -this._layoutProvider.getScrollLeft()); // TODO@Alex } diff --git a/src/vs/editor/browser/viewParts/overviewRuler/overviewRulerImpl.ts b/src/vs/editor/browser/viewParts/overviewRuler/overviewRulerImpl.ts index 99c0a38f05e..7f973313cba 100644 --- a/src/vs/editor/browser/viewParts/overviewRuler/overviewRulerImpl.ts +++ b/src/vs/editor/browser/viewParts/overviewRuler/overviewRulerImpl.ts @@ -285,9 +285,6 @@ export class OverviewRulerImpl { this._domNode = document.createElement('canvas'); this._domNode.className = cssClassName; this._domNode.style.position = 'absolute'; - if (browser.canUseTranslate3d) { - this._domNode.style.transform = 'translate3d(0px, 0px, 0px)'; - } this._lanesCount = 3; @@ -383,6 +380,11 @@ export class OverviewRulerImpl { if (this._zoneManager.getOuterHeight() === 0) { return false; } + if (browser.canUseTranslate3d) { + StyleMutator.setTransform(this._domNode, 'translate3d(0px, 0px, 0px)'); + } else { + StyleMutator.setTransform(this._domNode, ''); + } const width = this._zoneManager.getWidth(); const height = this._zoneManager.getHeight(); diff --git a/src/vs/editor/browser/viewParts/viewCursors/viewCursors.ts b/src/vs/editor/browser/viewParts/viewCursors/viewCursors.ts index c1cb866fd4d..d588d199ce8 100644 --- a/src/vs/editor/browser/viewParts/viewCursors/viewCursors.ts +++ b/src/vs/editor/browser/viewParts/viewCursors/viewCursors.ts @@ -13,6 +13,7 @@ import {ViewPart} from 'vs/editor/browser/view/viewPart'; import {ViewCursor} from 'vs/editor/browser/viewParts/viewCursors/viewCursor'; import {ViewContext} from 'vs/editor/common/view/viewContext'; import {IRenderingContext, IRestrictedRenderingContext} from 'vs/editor/common/view/renderingContext'; +import {FastDomNode, createFastDomNode} from 'vs/base/browser/styleMutator'; enum RenderType { Hidden, @@ -30,7 +31,7 @@ export class ViewCursors extends ViewPart { private _isVisible: boolean; - private _domNode: HTMLElement; + private _domNode: FastDomNode; private _blinkTimer: number; @@ -49,13 +50,10 @@ export class ViewCursors extends ViewPart { this._primaryCursor = new ViewCursor(this._context, false); this._secondaryCursors = []; - this._domNode = document.createElement('div'); + this._domNode = createFastDomNode(document.createElement('div')); this._updateDomClassName(); - if (browser.canUseTranslate3d) { - this._domNode.style.transform = 'translate3d(0px, 0px, 0px)'; - } - this._domNode.appendChild(this._primaryCursor.getDomNode()); + this._domNode.domNode.appendChild(this._primaryCursor.getDomNode()); this._blinkTimer = -1; @@ -72,7 +70,7 @@ export class ViewCursors extends ViewPart { } public getDomNode(): HTMLElement { - return this._domNode; + return this._domNode.domNode; } // --- begin event handlers @@ -227,7 +225,7 @@ export class ViewCursors extends ViewPart { // --- end blinking logic private _updateDomClassName(): void { - this._domNode.className = this._getClassName(); + this._domNode.setClassName(this._getClassName()); } private _getClassName(): string { @@ -291,5 +289,11 @@ export class ViewCursors extends ViewPart { for (var i = 0, len = this._secondaryCursors.length; i < len; i++) { this._secondaryCursors[i].render(ctx); } + + if (browser.canUseTranslate3d) { + this._domNode.setTransform('translate3d(0px, 0px, 0px)'); + } else { + this._domNode.setTransform(''); + } } } diff --git a/src/vs/editor/contrib/suggest/browser/suggestWidget.ts b/src/vs/editor/contrib/suggest/browser/suggestWidget.ts index 8d10dcfea5b..eab66e6a63d 100644 --- a/src/vs/editor/contrib/suggest/browser/suggestWidget.ts +++ b/src/vs/editor/contrib/suggest/browser/suggestWidget.ts @@ -221,7 +221,7 @@ class SuggestionDetails { this.back.title = nls.localize('goback', "Go back"); this.body = $('.body'); - this.scrollbar = new DomScrollableElement(this.body, {}); + this.scrollbar = new DomScrollableElement(this.body, { canUseTranslate3d: false }); append(this.el, this.scrollbar.getDomNode()); this.disposables.push(this.scrollbar); diff --git a/src/vs/workbench/browser/parts/editor/binaryDiffEditor.ts b/src/vs/workbench/browser/parts/editor/binaryDiffEditor.ts index 1ae8b918f0d..82e50e1642b 100644 --- a/src/vs/workbench/browser/parts/editor/binaryDiffEditor.ts +++ b/src/vs/workbench/browser/parts/editor/binaryDiffEditor.ts @@ -58,7 +58,7 @@ export class BinaryResourceDiffEditor extends BaseEditor implements IVerticalSas this.leftBinaryContainer.tabindex(0); // enable focus support from the editor part (do not remove) // Left Custom Scrollbars - this.leftScrollbar = new DomScrollableElement(leftBinaryContainerElement, { horizontal: 'hidden', vertical: 'hidden' }); + this.leftScrollbar = new DomScrollableElement(leftBinaryContainerElement, { canUseTranslate3d: false, horizontal: 'hidden', vertical: 'hidden' }); parent.getHTMLElement().appendChild(this.leftScrollbar.getDomNode()); $(this.leftScrollbar.getDomNode()).addClass('binarydiff-left'); @@ -76,7 +76,7 @@ export class BinaryResourceDiffEditor extends BaseEditor implements IVerticalSas this.rightBinaryContainer.tabindex(0); // enable focus support from the editor part (do not remove) // Right Custom Scrollbars - this.rightScrollbar = new DomScrollableElement(rightBinaryContainerElement, { horizontal: 'hidden', vertical: 'hidden' }); + this.rightScrollbar = new DomScrollableElement(rightBinaryContainerElement, { canUseTranslate3d: false,horizontal: 'hidden', vertical: 'hidden' }); parent.getHTMLElement().appendChild(this.rightScrollbar.getDomNode()); $(this.rightScrollbar.getDomNode()).addClass('binarydiff-right'); } From 954f86dc1de7d4ca07bbbc38049ffb4d837f3199 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 6 May 2016 11:13:05 +0200 Subject: [PATCH 075/297] Remove workerStatusReporter --- src/vs/editor/browser/editor.all.ts | 1 - .../browser/workerStatusReporter.css | 28 ------ .../browser/workerStatusReporter.ts | 96 ------------------- .../platform/test/common/nullThreadService.ts | 9 +- .../thread/common/extHostThreadService.ts | 10 +- .../thread/common/mainThreadService.ts | 53 +--------- src/vs/platform/thread/common/thread.ts | 15 --- .../thread/common/workerThreadService.ts | 10 +- 8 files changed, 4 insertions(+), 218 deletions(-) delete mode 100644 src/vs/editor/contrib/workerStatusReporter/browser/workerStatusReporter.css delete mode 100644 src/vs/editor/contrib/workerStatusReporter/browser/workerStatusReporter.ts diff --git a/src/vs/editor/browser/editor.all.ts b/src/vs/editor/browser/editor.all.ts index 8bb01e10057..9a3a4165faa 100644 --- a/src/vs/editor/browser/editor.all.ts +++ b/src/vs/editor/browser/editor.all.ts @@ -40,7 +40,6 @@ import 'vs/editor/contrib/toggleTabFocusMode/common/toggleTabFocusMode'; import 'vs/editor/contrib/toggleWordWrap/common/toggleWordWrap'; import 'vs/css!vs/editor/contrib/wordHighlighter/browser/wordHighlighter'; import 'vs/editor/contrib/wordHighlighter/common/wordHighlighter'; -import 'vs/editor/contrib/workerStatusReporter/browser/workerStatusReporter'; import 'vs/editor/contrib/defineKeybinding/browser/defineKeybinding'; import 'vs/editor/contrib/folding/browser/folding'; import 'vs/editor/contrib/indentation/common/indentation'; diff --git a/src/vs/editor/contrib/workerStatusReporter/browser/workerStatusReporter.css b/src/vs/editor/contrib/workerStatusReporter/browser/workerStatusReporter.css deleted file mode 100644 index e49642ac725..00000000000 --- a/src/vs/editor/contrib/workerStatusReporter/browser/workerStatusReporter.css +++ /dev/null @@ -1,28 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -.monaco-worker-status .worker { - display: inline-block; - width: 1em; - height: 1em; -} - -.monaco-worker-status .worker[status=unknown]:before { - content: '?'; -} - -.monaco-worker-status .worker[status=idle]:before { - content: '\25CA'; - color: rgb(130, 194, 130); -} - -.monaco-worker-status .worker[status=busy]:before { - content: '\2666'; -} - -.monaco-worker-status .worker[status=flooded]:before { - content: '\2666'; - color: red; -} \ No newline at end of file diff --git a/src/vs/editor/contrib/workerStatusReporter/browser/workerStatusReporter.ts b/src/vs/editor/contrib/workerStatusReporter/browser/workerStatusReporter.ts deleted file mode 100644 index 31d8aa7b521..00000000000 --- a/src/vs/editor/contrib/workerStatusReporter/browser/workerStatusReporter.ts +++ /dev/null @@ -1,96 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -'use strict'; - -import 'vs/css!./workerStatusReporter'; -import {IDisposable, dispose} from 'vs/base/common/lifecycle'; -import * as browser from 'vs/base/browser/browser'; -import {IThreadService, IThreadServiceStatus, IThreadServiceStatusListener} from 'vs/platform/thread/common/thread'; -import {IEditorContribution} from 'vs/editor/common/editorCommon'; -import {ICodeEditor, IOverlayWidgetPosition, OverlayWidgetPositionPreference} from 'vs/editor/browser/editorBrowser'; - -class WorkerStatusReporter implements IEditorContribution, IThreadServiceStatusListener { - - public static ID = 'editor.contrib.workerStatusReporter'; - - private _editor:ICodeEditor; - private _toDispose:IDisposable[]; - private _threadService:IThreadService; - - private _domNode:HTMLElement; - private _domNodes:HTMLElement[]; - - constructor(editor:ICodeEditor, @IThreadService threadService: IThreadService) { - this._threadService = threadService; - this._threadService.addStatusListener(this); - this._editor = editor; - this._toDispose = []; - - this._domNodes = []; - - this._domNode = document.createElement('div'); - this._domNode.className = 'monaco-worker-status'; - if (browser.canUseTranslate3d) { - // Put the worker reporter in its own layer - this._domNode.style.transform = 'translate3d(0px, 0px, 0px)'; - } - this._editor.addOverlayWidget(this); - } - - public getId():string { - return WorkerStatusReporter.ID; - } - - public dispose(): void { - this._threadService.removeStatusListener(this); - this._toDispose = dispose(this._toDispose); - } - - public getDomNode():HTMLElement { - return this._domNode; - } - - public getPosition():IOverlayWidgetPosition { - return { preference: OverlayWidgetPositionPreference.TOP_RIGHT_CORNER }; - } - - private _ensureDomNodes(desiredCount:number): void { - // Remove extra dom nodes - for (var i = this._domNodes.length - 1; i >= desiredCount; i++) { - this._domNode.removeChild(this._domNodes[i]); - this._domNodes.splice(i, 1); - } - - // Create new dom nodes - for (var i = this._domNodes.length; i < desiredCount; i++) { - this._domNodes[i] = document.createElement('div'); - this._domNodes[i].className = 'worker'; - this._domNode.appendChild(this._domNodes[i]); - } - } - - public onThreadServiceStatus(status:IThreadServiceStatus): void { - this._ensureDomNodes(status.workers.length); - for (var i = 0; i < status.workers.length; i++) { - var cnt = status.workers[i].queueSize; - var workerStatus = 'idle'; - if (cnt > 5) { - workerStatus = 'flooded'; - } else if (cnt > 0) { - workerStatus = 'busy'; - } - attr(this._domNodes[i], 'status', workerStatus); - } - } -} - -function attr(target:HTMLElement, attrName:string, attrValue:string): void { - target.setAttribute(attrName, attrValue); -} - -// if (false) { //TODO@Debt -// EditorBrowserRegistry.registerEditorContribution(WorkerStatusReporter); -// } \ No newline at end of file diff --git a/src/vs/platform/test/common/nullThreadService.ts b/src/vs/platform/test/common/nullThreadService.ts index 300f1acf082..505c404e014 100644 --- a/src/vs/platform/test/common/nullThreadService.ts +++ b/src/vs/platform/test/common/nullThreadService.ts @@ -9,7 +9,7 @@ import abstractThreadService = require('vs/platform/thread/common/abstractThread import {InstantiationService} from 'vs/platform/instantiation/common/instantiationService'; import {ServiceCollection} from 'vs/platform/instantiation/common/serviceCollection'; import {SyncDescriptor0} from 'vs/platform/instantiation/common/descriptors'; -import {IThreadService, IThreadServiceStatusListener, IThreadSynchronizableObject, ThreadAffinity} from 'vs/platform/thread/common/thread'; +import {IThreadService, IThreadSynchronizableObject, ThreadAffinity} from 'vs/platform/thread/common/thread'; export class NullThreadService extends abstractThreadService.AbstractThreadService implements IThreadService { public serviceId = IThreadService; @@ -31,13 +31,6 @@ export class NullThreadService extends abstractThreadService.AbstractThreadServi return winjs.TPromise.as(null); } - addStatusListener(listener: IThreadServiceStatusListener): void { - // Nothing to do - } - - removeStatusListener(listener: IThreadServiceStatusListener): void { - // Nothing to do - } protected _registerAndInstantiateMainProcessActor(id: string, descriptor: SyncDescriptor0): T { return this._getOrCreateLocalInstance(id, descriptor); diff --git a/src/vs/platform/thread/common/extHostThreadService.ts b/src/vs/platform/thread/common/extHostThreadService.ts index 2f8d2c1e3a6..71ddfcc93fd 100644 --- a/src/vs/platform/thread/common/extHostThreadService.ts +++ b/src/vs/platform/thread/common/extHostThreadService.ts @@ -9,7 +9,7 @@ import remote = require('vs/base/common/remote'); import descriptors = require('vs/platform/instantiation/common/descriptors'); import abstractThreadService = require('./abstractThreadService'); -import {IThreadService, IThreadSynchronizableObject, ThreadAffinity, IThreadServiceStatusListener} from 'vs/platform/thread/common/thread'; +import {IThreadService, IThreadSynchronizableObject, ThreadAffinity} from 'vs/platform/thread/common/thread'; export class ExtHostThreadService extends abstractThreadService.AbstractThreadService implements IThreadService { public serviceId = IThreadService; @@ -29,14 +29,6 @@ export class ExtHostThreadService extends abstractThreadService.AbstractThreadSe return TPromise.as(null); } - addStatusListener(listener: IThreadServiceStatusListener): void { - // Nothing to do - } - - removeStatusListener(listener: IThreadServiceStatusListener): void { - // Nothing to do - } - protected _registerAndInstantiateMainProcessActor(id: string, descriptor: descriptors.SyncDescriptor0): T { return this._getOrCreateProxyInstance(this._remoteCom, id, descriptor); } diff --git a/src/vs/platform/thread/common/mainThreadService.ts b/src/vs/platform/thread/common/mainThreadService.ts index edbad2ce4a9..4b9fb32a2ae 100644 --- a/src/vs/platform/thread/common/mainThreadService.ts +++ b/src/vs/platform/thread/common/mainThreadService.ts @@ -9,11 +9,10 @@ import Worker = require('vs/base/common/worker/workerClient'); import abstractThreadService = require('vs/platform/thread/common/abstractThreadService'); import Env = require('vs/base/common/flags'); import Platform = require('vs/base/common/platform'); -import errors = require('vs/base/common/errors'); import Timer = require('vs/base/common/timer'); import remote = require('vs/base/common/remote'); import {SyncDescriptor0} from 'vs/platform/instantiation/common/descriptors'; -import {IThreadService, IThreadServiceStatusListener, IThreadSynchronizableObject, ThreadAffinity, IThreadServiceStatus} from 'vs/platform/thread/common/thread'; +import {IThreadService, IThreadSynchronizableObject, ThreadAffinity} from 'vs/platform/thread/common/thread'; import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace'; import {DefaultWorkerFactory} from 'vs/base/worker/defaultWorkerFactory'; @@ -39,7 +38,6 @@ export class MainThreadService extends abstractThreadService.AbstractThreadServi private _workersCreatedPromise: TPromise; private _triggerWorkersCreatedPromise: (value: void) => void; - private _listeners: IThreadServiceStatusListener[]; private _workerFactory: Worker.IWorkerFactory; private _workerModuleId: string; @@ -58,7 +56,6 @@ export class MainThreadService extends abstractThreadService.AbstractThreadServi this._workerPool = []; this._affinityScrambler = {}; - this._listeners = []; this._workersCreatedPromise = new TPromise((c, e, p) => { this._triggerWorkersCreatedPromise = c; @@ -90,25 +87,6 @@ export class MainThreadService extends abstractThreadService.AbstractThreadServi } } - addStatusListener(listener: IThreadServiceStatusListener): void { - for (let i = 0; i < this._listeners.length; i++) { - if (this._listeners[i] === listener) { - // listener is already in - return; - } - } - this._listeners.push(listener); - } - - removeStatusListener(listener: IThreadServiceStatusListener): void { - for (let i = 0; i < this._listeners.length; i++) { - if (this._listeners[i] === listener) { - this._listeners.splice(i, 1); - return; - } - } - } - private _afterWorkers(): TPromise { let shouldCancelPromise = false; @@ -218,43 +196,14 @@ export class MainThreadService extends abstractThreadService.AbstractThreadServi let stopTimer = () => { timerEvent.stop(); // console.log(timerEvent.timeTaken(), this._workerPool.indexOf(worker), obj.getId() + ' >>> ' + methodName + ': ', params); - this._pingListenersIfNecessary(); }; let r = decoratePromise(worker.request('threadService', [id, methodName, params]), stopTimer, stopTimer); - this._pingListenersIfNecessary(); - return r; } - private _pingListenersIfNecessary(): void { - if (this._listeners.length > 0) { - let status = this._buildStatus(); - let listeners = this._listeners.slice(0); - try { - for (let i = 0; i < listeners.length; i++) { - listeners[i].onThreadServiceStatus(status); - } - } catch (e) { - errors.onUnexpectedError(e); - } - } - } - - private _buildStatus(): IThreadServiceStatus { - let queueSizes = this._workerPool.map((worker) => { - return { - queueSize: worker.getQueueSize() - }; - }); - - return { - workers: queueSizes - }; - } - protected _registerAndInstantiateMainProcessActor(id: string, descriptor: SyncDescriptor0): T { return this._getOrCreateLocalInstance(id, descriptor); } diff --git a/src/vs/platform/thread/common/thread.ts b/src/vs/platform/thread/common/thread.ts index 7485601ce42..147cba02315 100644 --- a/src/vs/platform/thread/common/thread.ts +++ b/src/vs/platform/thread/common/thread.ts @@ -18,9 +18,6 @@ export interface IThreadService { // --- BEGIN deprecated methods isInMainThread: boolean; - addStatusListener(listener: IThreadServiceStatusListener): void; - removeStatusListener(listener: IThreadServiceStatusListener): void; - OneWorker(obj: IThreadSynchronizableObject, methodName: string, target: Function, param: any[], affinity: ThreadAffinity): TPromise; AllWorkers(obj: IThreadSynchronizableObject, methodName: string, target: Function, param: any[]): TPromise; @@ -114,15 +111,3 @@ export enum ThreadAffinity { Group9 = 9, All = 10 } - -export interface IWorkerStatus { - queueSize: number; -} - -export interface IThreadServiceStatus { - workers: IWorkerStatus[]; -} - -export interface IThreadServiceStatusListener { - onThreadServiceStatus(status: IThreadServiceStatus): void; -} diff --git a/src/vs/platform/thread/common/workerThreadService.ts b/src/vs/platform/thread/common/workerThreadService.ts index 61643664345..11e342bf45a 100644 --- a/src/vs/platform/thread/common/workerThreadService.ts +++ b/src/vs/platform/thread/common/workerThreadService.ts @@ -8,7 +8,7 @@ import {TPromise} from 'vs/base/common/winjs.base'; import abstractThreadService = require('vs/platform/thread/common/abstractThreadService'); import remote = require('vs/base/common/remote'); import {SyncDescriptor0} from 'vs/platform/instantiation/common/descriptors'; -import {IThreadService, IThreadServiceStatusListener, IThreadSynchronizableObject, ThreadAffinity} from 'vs/platform/thread/common/thread'; +import {IThreadService, IThreadSynchronizableObject, ThreadAffinity} from 'vs/platform/thread/common/thread'; export class WorkerThreadService extends abstractThreadService.AbstractThreadService implements IThreadService { public serviceId = IThreadService; @@ -56,14 +56,6 @@ export class WorkerThreadService extends abstractThreadService.AbstractThreadSer return target.apply(obj, params); } - addStatusListener(listener: IThreadServiceStatusListener): void { - // Nothing to do - } - - removeStatusListener(listener: IThreadServiceStatusListener): void { - // Nothing to do - } - protected _registerAndInstantiateMainProcessActor(id: string, descriptor: SyncDescriptor0): T { return this._getOrCreateProxyInstance(this._remoteCom, id, descriptor); } From d9990fd5b7c0744af878c160456baabca3fc0537 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 6 May 2016 11:38:20 +0200 Subject: [PATCH 076/297] Remove unnecessary browserService and mockDom --- src/vs/base/browser/browser.ts | 20 - src/vs/base/browser/browserService.ts | 66 -- src/vs/base/browser/builder.ts | 27 +- src/vs/base/browser/dom.ts | 6 +- src/vs/base/browser/idleMonitor.ts | 5 +- src/vs/base/browser/ui/inputbox/inputBox.ts | 3 +- src/vs/base/test/browser/browser.test.ts | 6 - .../base/test/browser/browserService.test.ts | 28 - .../base/test/browser/mockBrowserService.ts | 28 - src/vs/base/test/browser/mockDom.test.ts | 73 -- src/vs/base/test/browser/mockDom.ts | 914 ------------------ 11 files changed, 19 insertions(+), 1157 deletions(-) delete mode 100644 src/vs/base/browser/browserService.ts delete mode 100644 src/vs/base/test/browser/browserService.test.ts delete mode 100644 src/vs/base/test/browser/mockBrowserService.ts delete mode 100644 src/vs/base/test/browser/mockDom.test.ts delete mode 100644 src/vs/base/test/browser/mockDom.ts diff --git a/src/vs/base/browser/browser.ts b/src/vs/base/browser/browser.ts index 9b06db9b402..166da83e90b 100644 --- a/src/vs/base/browser/browser.ts +++ b/src/vs/base/browser/browser.ts @@ -68,22 +68,6 @@ export const canUseTranslate3d = !isIE9 && !isFirefox; export const enableEmptySelectionClipboard = isWebKit; -let _disablePushState = false; - -/** - * Returns if the browser supports the history.pushState function or not. - */ -export function canPushState() { - return (!_disablePushState && globals.history && globals.history.pushState); -} - -/** - * Helpful when we detect that pushing state does not work for some reason (e.g. FF prevents pushState for security reasons in some cases) - */ -export function disablePushState() { - _disablePushState = true; -} - /** * Returns if the browser supports CSS 3 animations. */ @@ -116,10 +100,6 @@ export function hasCSSAnimationSupport() { return this._hasCSSAnimationSupport; } -export function isInWebWorker(): boolean { - return !globals.document && typeof ((globals).importScripts) !== 'undefined'; -} - export function supportsExecCommand(command: string): boolean { return ( (isIE11orEarlier || Platform.isNative) diff --git a/src/vs/base/browser/browserService.ts b/src/vs/base/browser/browserService.ts deleted file mode 100644 index 066a4db10ca..00000000000 --- a/src/vs/base/browser/browserService.ts +++ /dev/null @@ -1,66 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -'use strict'; - -import {isInWebWorker} from 'vs/base/browser/browser'; - -export interface IBrowserServiceData { - document: Document; - window: Window; - isHTMLElement: (o: any) => boolean; -} - -export interface IBrowserService extends IBrowserServiceData { - /** - * Mock the DOM with dummy objects - */ - mock(source: IBrowserServiceData): void; - - /** - * Restore the normal DOM - */ - restore(): void; -} - -export function regularIsHTMLElement(o: any): boolean { - if (typeof HTMLElement === 'object') { - return o instanceof HTMLElement; - } - return o && typeof o === 'object' && o.nodeType === 1 && typeof o.nodeName === 'string'; -} - -class BrowserService implements IBrowserService { - - public document: Document; - public window: Window; - public isHTMLElement: (o: any) => boolean; - - constructor() { - this.restore(); - } - - public mock(source: IBrowserServiceData): void { - this.document = source.document; - this.window = source.window; - this.isHTMLElement = source.isHTMLElement; - } - - public restore(): void { - this.isHTMLElement = regularIsHTMLElement; - if (isInWebWorker()) { - this.document = null; - this.window = null; - } else { - this.document = window.document; - this.window = window; - } - } -} - -const browserService = new BrowserService(); - -export function getService(): IBrowserService { - return browserService; -} \ No newline at end of file diff --git a/src/vs/base/browser/builder.ts b/src/vs/base/browser/builder.ts index 3b66f354b76..8be28aba069 100644 --- a/src/vs/base/browser/builder.ts +++ b/src/vs/base/browser/builder.ts @@ -11,7 +11,6 @@ import {IDisposable, dispose} from 'vs/base/common/lifecycle'; import strings = require('vs/base/common/strings'); import assert = require('vs/base/common/assert'); import DOM = require('vs/base/browser/dom'); -import BrowserService = require('vs/base/browser/browserService'); /** * Welcome to the monaco builder. The recommended way to use it is: @@ -52,7 +51,7 @@ export interface QuickBuilder { export function withElementById(id: string, offdom?: boolean): Builder { assert.ok(types.isString(id), 'Expected String as parameter'); - let element = BrowserService.getService().document.getElementById(id); + let element = document.getElementById(id); if (element) { return new Builder(element, offdom); } @@ -136,7 +135,6 @@ export class Builder implements IDisposable { private createdElements: HTMLElement[]; private toUnbind: { [type: string]: IDisposable[]; }; private captureToUnbind: { [type: string]: IDisposable[]; }; - private browserService: BrowserService.IBrowserService; constructor(element?: HTMLElement, offdom?: boolean) { this.offdom = offdom; @@ -148,7 +146,6 @@ export class Builder implements IDisposable { this.toUnbind = {}; this.captureToUnbind = {}; - this.browserService = BrowserService.getService(); } /** @@ -476,7 +473,7 @@ export class Builder implements IDisposable { private doElement(name: string, attributesOrFn?: any, fn?: (builder: Builder) => void): Builder { // Create Element - let element = this.browserService.document.createElement(name); + let element = document.createElement(name); this.currentElement = element; // Off-DOM: Remember in array of created elements @@ -521,7 +518,7 @@ export class Builder implements IDisposable { * Returns true if the current element of this builder is the active element. */ public hasFocus(): boolean { - let activeElement: Element = this.browserService.document.activeElement; + let activeElement: Element = document.activeElement; return (activeElement === this.currentElement); } @@ -1535,7 +1532,7 @@ export class Builder implements IDisposable { else { // if there are elements inside this node, append the string as a new text node // to avoid wiping out the innerHTML and replacing it with only text content - this.currentElement.appendChild(this.browserService.document.createTextNode(text)); + this.currentElement.appendChild(document.createTextNode(text)); } } else { this.currentElement.textContent = text; @@ -1848,24 +1845,24 @@ export class Builder implements IDisposable { public getClientArea(): Dimension { // 0.) Try with DOM getDomNodePosition - if (this.currentElement !== this.browserService.document.body) { + if (this.currentElement !== document.body) { let dimensions = DOM.getDomNodePosition(this.currentElement); return new Dimension(dimensions.width, dimensions.height); } // 1.) Try innerWidth / innerHeight - if (this.browserService.window.innerWidth && this.browserService.window.innerHeight) { - return new Dimension(this.browserService.window.innerWidth, this.browserService.window.innerHeight); + if (window.innerWidth && window.innerHeight) { + return new Dimension(window.innerWidth, window.innerHeight); } // 2.) Try with document.body.clientWidth / document.body.clientHeigh - if (this.browserService.document.body && this.browserService.document.body.clientWidth && this.browserService.document.body.clientWidth) { - return new Dimension(this.browserService.document.body.clientWidth, this.browserService.document.body.clientHeight); + if (document.body && document.body.clientWidth && document.body.clientWidth) { + return new Dimension(document.body.clientWidth, document.body.clientHeight); } // 3.) Try with document.documentElement.clientWidth / document.documentElement.clientHeight - if (this.browserService.document.documentElement && this.browserService.document.documentElement.clientWidth && this.browserService.document.documentElement.clientHeight) { - return new Dimension(this.browserService.document.documentElement.clientWidth, this.browserService.document.documentElement.clientHeight); + if (document.documentElement && document.documentElement.clientWidth && document.documentElement.clientHeight) { + return new Dimension(document.documentElement.clientWidth, document.documentElement.clientHeight); } throw new Error('Unable to figure out browser width and height'); @@ -2154,7 +2151,7 @@ export let $: QuickBuilder = function(arg?: any): Builder { // Use the argument as HTML code if (arg[0] === '<') { let element: Node; - let container = BrowserService.getService().document.createElement('div'); + let container = document.createElement('div'); container.innerHTML = strings.format.apply(strings, arguments); if (container.children.length === 0) { diff --git a/src/vs/base/browser/dom.ts b/src/vs/base/browser/dom.ts index db5139796cc..5f5aa6c92a2 100644 --- a/src/vs/base/browser/dom.ts +++ b/src/vs/base/browser/dom.ts @@ -10,7 +10,6 @@ import {EventEmitter} from 'vs/base/common/eventEmitter'; import {Disposable, IDisposable} from 'vs/base/common/lifecycle'; import {isObject} from 'vs/base/common/types'; import {isChrome, isWebKit} from 'vs/base/browser/browser'; -import {getService} from 'vs/base/browser/browserService'; import {IKeyboardEvent, StandardKeyboardEvent} from 'vs/base/browser/keyboardEvent'; import {IMouseEvent, StandardMouseEvent} from 'vs/base/browser/mouseEvent'; @@ -764,7 +763,10 @@ export function removeCSSRulesWithPrefix(ruleName: string, style = sharedStyle): } export function isHTMLElement(o: any): o is HTMLElement { - return getService().isHTMLElement(o); + if (typeof HTMLElement === 'object') { + return o instanceof HTMLElement; + } + return o && typeof o === 'object' && o.nodeType === 1 && typeof o.nodeName === 'string'; } export const EventType = { diff --git a/src/vs/base/browser/idleMonitor.ts b/src/vs/base/browser/idleMonitor.ts index 4268a7b4fc9..fbd3a7584b8 100644 --- a/src/vs/base/browser/idleMonitor.ts +++ b/src/vs/base/browser/idleMonitor.ts @@ -7,7 +7,6 @@ import {TimeoutTimer} from 'vs/base/common/async'; import {EventEmitter} from 'vs/base/common/eventEmitter'; import {Disposable, IDisposable} from 'vs/base/common/lifecycle'; -import {getService} from 'vs/base/browser/browserService'; import * as dom from 'vs/base/browser/dom'; export enum UserStatus { @@ -34,8 +33,8 @@ export class IdleMonitor extends Disposable { this._idleTime = idleTime; this._eventEmitter = this._register(new EventEmitter()); - this._register(dom.addDisposableListener(getService().document, 'mousemove', () => this._onUserActive())); - this._register(dom.addDisposableListener(getService().document, 'keydown', () => this._onUserActive())); + this._register(dom.addDisposableListener(document, 'mousemove', () => this._onUserActive())); + this._register(dom.addDisposableListener(document, 'keydown', () => this._onUserActive())); this._onUserActive(); } diff --git a/src/vs/base/browser/ui/inputbox/inputBox.ts b/src/vs/base/browser/ui/inputbox/inputBox.ts index 3ccb29fbf6c..5013288e7da 100644 --- a/src/vs/base/browser/ui/inputbox/inputBox.ts +++ b/src/vs/base/browser/ui/inputbox/inputBox.ts @@ -9,7 +9,6 @@ import 'vs/css!./inputBox'; import nls = require('vs/nls'); import * as Bal from 'vs/base/browser/browser'; import * as dom from 'vs/base/browser/dom'; -import * as browser from 'vs/base/browser/browserService'; import {IHTMLContentElement} from 'vs/base/common/htmlContent'; import {renderHtml} from 'vs/base/browser/htmlContentRenderer'; import aria = require('vs/base/browser/ui/aria/aria'); @@ -204,7 +203,7 @@ export class InputBox extends Widget { } public hasFocus(): boolean { - return browser.getService().document.activeElement === this.input; + return document.activeElement === this.input; } public select(range: IRange = null): void { diff --git a/src/vs/base/test/browser/browser.test.ts b/src/vs/base/test/browser/browser.test.ts index 65ae88ec8e6..feb8cab8d0c 100644 --- a/src/vs/base/test/browser/browser.test.ts +++ b/src/vs/base/test/browser/browser.test.ts @@ -19,35 +19,29 @@ suite('Browsers', () => { var isChrome = browser.isChrome; var isSafari = browser.isSafari; - var canPushState = browser.canPushState(); var hasCSSAnimations = browser.hasCSSAnimationSupport(); var browserCount = 0; if (isOpera) { browserCount++; - assert(canPushState); } if (isIE11orEarlier) { browserCount++; } if (isFirefox) { browserCount++; - assert(canPushState); assert(hasCSSAnimations); } if (isWebKit) { browserCount++; - assert(canPushState); assert(hasCSSAnimations); } if (isChrome) { browserCount++; - assert(canPushState); assert(hasCSSAnimations); } if (isSafari) { browserCount++; - assert(canPushState); assert(hasCSSAnimations); } }); diff --git a/src/vs/base/test/browser/browserService.test.ts b/src/vs/base/test/browser/browserService.test.ts deleted file mode 100644 index f72160f82cd..00000000000 --- a/src/vs/base/test/browser/browserService.test.ts +++ /dev/null @@ -1,28 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -'use strict'; - -import * as assert from 'assert'; -import BrowserService = require('vs/base/browser/browserService'); -import { MockBrowserServiceData } from 'vs/base/test/browser/mockBrowserService'; - -suite('BrowserService', () => { - test('Mocking of Window', () => { - try { - var service = BrowserService.getService(); - service.mock(new MockBrowserServiceData()); - var w = service.window; - w.testValue = 42; - service.restore(); - w = service.window; - assert.strictEqual(w.testValue, undefined); - } - finally { - if(service) { - service.restore(); - } - } - }); -}); diff --git a/src/vs/base/test/browser/mockBrowserService.ts b/src/vs/base/test/browser/mockBrowserService.ts deleted file mode 100644 index cdd2ed79ae6..00000000000 --- a/src/vs/base/test/browser/mockBrowserService.ts +++ /dev/null @@ -1,28 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -'use strict'; - -import { MockDocument, MockWindow, MockElement } from 'vs/base/test/browser/mockDom'; -import browserService = require('vs/base/browser/browserService'); - -function mockedIsHTMLElement(o:any): boolean { - if (typeof HTMLElement === 'object') { - return o instanceof HTMLElement || o instanceof MockElement; - } - return o && typeof o === 'object' && o.nodeType === 1 && typeof o.nodeName === 'string'; -} - -export class MockBrowserServiceData implements browserService.IBrowserServiceData { - - public document:Document; - public window:Window; - public isHTMLElement: (o:any)=>boolean; - - constructor() { - this.document = new MockDocument(); - this.window = new MockWindow(); - this.isHTMLElement = mockedIsHTMLElement; - } -} \ No newline at end of file diff --git a/src/vs/base/test/browser/mockDom.test.ts b/src/vs/base/test/browser/mockDom.test.ts deleted file mode 100644 index 2c6f8be1af4..00000000000 --- a/src/vs/base/test/browser/mockDom.test.ts +++ /dev/null @@ -1,73 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -'use strict'; - -import * as assert from 'assert'; -import MockDom = require('vs/base/test/browser/mockDom'); - -suite('MockDom', () => { - test('Create Element', () => { - var doc = new MockDom.MockDocument(); - var div = doc.createElement('div'); - div.textContent = 'test'; - assert.strictEqual(div.textContent, 'test'); - assert.strictEqual(div.tagName, 'div'); - }); - - test('Events', () => { - var doc = new MockDom.MockDocument(); - var div = doc.createElement('div'); - var fakeEvent = { type: 'test'}; - var count = 0; - var callback = function(event:any) { - assert.strictEqual(event, fakeEvent); - count++; - }; - div.addEventListener('test', callback); - div.dispatchEvent(fakeEvent); - assert.strictEqual(count, 1); - div.removeEventListener('test', callback); - div.dispatchEvent(fakeEvent); - assert.strictEqual(count, 1); - }); - - test('Create elements via innerHTML', () => { - var doc = new MockDom.MockDocument(); - var div = doc.createElement('div'); - div.innerHTML = '
test
'; - assert.strictEqual(div.children.length, 1); - assert.strictEqual(div.childNodes[0], div.children[0]); - assert.strictEqual(div.children[0], div.firstElementChild); - assert.strictEqual(div.firstElementChild, div.firstChild); - var child = div.children[0]; - - assert.strictEqual(child.id, 'testId'); - assert.strictEqual(child.getAttribute('id'), 'testId'); - assert.strictEqual(child.childElementCount, 1); - - var grandchild = child.firstElementChild; - assert.strictEqual(grandchild.tagName, 'span'); - assert.strictEqual(grandchild.className, 'testClass'); - - assert.strictEqual(grandchild.textContent, 'test'); - }); - - test('Convert elements to innerHTML', () => { - var doc = new MockDom.MockDocument(); - var div = doc.createElement('div'); - - var child = doc.createElement('div'); - child.id = 'testId'; - - var grandchild = doc.createElement('span'); - grandchild.className = 'testClass'; - grandchild.textContent = 'test'; - child.appendChild(grandchild); - div.appendChild(child); - - assert.strictEqual(div.innerHTML, '
test
'); - assert.strictEqual(div.outerHTML, '
test
'); - }); -}); \ No newline at end of file diff --git a/src/vs/base/test/browser/mockDom.ts b/src/vs/base/test/browser/mockDom.ts deleted file mode 100644 index 4a4db90e43b..00000000000 --- a/src/vs/base/test/browser/mockDom.ts +++ /dev/null @@ -1,914 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -'use strict'; - -interface IEventMap { - [name: string]: EventListener[]; -} - -export class MockEventTarget implements EventTarget { - - private eventMap:IEventMap; - - constructor() { - this.eventMap = {}; - } - - removeEventListener(type: string, listener: EventListener, useCapture?: boolean): void { - if(type in this.eventMap) { - var a = this.eventMap[type]; - a.splice(a.indexOf(listener), 1); - } - } - - addEventListener(type: string, listener: EventListener, useCapture?: boolean): void { - if(type in this.eventMap) { - this.eventMap[type].push(listener); - } - else { - this.eventMap[type] = [listener]; - } - } - - dispatchEvent(evt: Event): boolean { - var listeners = this.eventMap[evt.type]; - if (listeners) { - listeners.forEach((listener) => { - listener(evt); - }); - } - return evt.defaultPrevented; - } -} - -export class MockNode extends MockEventTarget implements Node { - // Added to make compiler happy. No real mocking - classList: DOMTokenList; - baseURI: string; - - parentElement: HTMLElement; - nodeType: number; - previousSibling: Node; - localName: string; - namespaceURI: string; - parentNode: Node; - nextSibling: Node; - nodeValue: string; - - public _childNodes: Node[]; - nodeName: string; - ownerDocument: Document; - _attributes: Attr[]; - - prefix: string; - - - constructor(name:string) { - super(); - this.nodeName = name; - this._childNodes = []; - this._attributes = []; - } - - public get attributes(): NamedNodeMap { - return this._attributes; - } - - public get lastChild(): Node { - return this._childNodes[this._childNodes.length - 1]; - } - public get firstChild(): Node { - return this._childNodes[0]; - } - - public get childNodes(): NodeList { - var a = this._childNodes; - if(!a.item) { - a.item = (function(index:number) { - return this[index]; - }).bind(a); - } - return a; - } - - public get textContent(): string { - - return this._childNodes.filter((node) => { - return node.nodeType === this.TEXT_NODE; - }).map((node) => { - return (node).wholeText; - }).join(''); - } - - public set textContent(value:string) { - this._childNodes = []; - this.appendChild(this.ownerDocument.createTextNode(value)); - } - - public removeChild(oldChild: Node): Node { - var i = this._childNodes.indexOf(oldChild); - if(i >= 0) { - var removed = this._childNodes.splice(i, 1); - return removed[0]; - } - return null; - } - - public contains(node: Node): boolean { - return this._childNodes.indexOf(node) !== -1; - } - - appendChild(newChild: Node): Node { - this._childNodes.push(newChild); - return newChild; - } - - isSupported(feature: string, version: string): boolean { - throw new Error('Not implemented!'); - } - isEqualNode(arg: Node): boolean { - throw new Error('Not implemented!'); - } - - lookupPrefix(namespaceURI: string): string { - throw new Error('Not implemented!'); - } - isDefaultNamespace(namespaceURI: string): boolean { - throw new Error('Not implemented!'); - } - compareDocumentPosition(other: Node): number { - throw new Error('Not implemented!'); - } - normalize(): void { - throw new Error('Not implemented!'); - } - isSameNode(other: Node): boolean { - return this === other; - } - hasAttributes(): boolean { - return this.attributes.length > 0; - } - lookupNamespaceURI(prefix: string): string { - throw new Error('Not implemented!'); - } - cloneNode(deep?: boolean): Node { - throw new Error('Not implemented!'); - } - hasChildNodes(): boolean { - return this.childNodes.length > 0; - } - replaceChild(newChild: Node, oldChild: Node): Node { - throw new Error('Not implemented!'); - } - insertBefore(newChild: Node, refChild?: Node): Node { - throw new Error('Not implemented!'); - } - ENTITY_REFERENCE_NODE: number = Node.ENTITY_REFERENCE_NODE; - ATTRIBUTE_NODE: number = Node.ATTRIBUTE_NODE; - DOCUMENT_FRAGMENT_NODE: number = Node.DOCUMENT_FRAGMENT_NODE; - TEXT_NODE: number = Node.TEXT_NODE; - ELEMENT_NODE: number = Node.ELEMENT_NODE; - COMMENT_NODE: number = Node.COMMENT_NODE; - DOCUMENT_POSITION_DISCONNECTED: number = Node.DOCUMENT_POSITION_DISCONNECTED; - DOCUMENT_POSITION_CONTAINED_BY: number = Node.DOCUMENT_POSITION_CONTAINED_BY; - DOCUMENT_POSITION_CONTAINS: number = Node.DOCUMENT_POSITION_CONTAINS; - DOCUMENT_TYPE_NODE: number = Node.DOCUMENT_TYPE_NODE; - DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC: number = Node.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC; - DOCUMENT_NODE: number = Node.DOCUMENT_NODE; - ENTITY_NODE: number = Node.ENTITY_NODE; - PROCESSING_INSTRUCTION_NODE: number = Node.PROCESSING_INSTRUCTION_NODE; - CDATA_SECTION_NODE: number = Node.CDATA_SECTION_NODE; - NOTATION_NODE: number = Node.NOTATION_NODE; - DOCUMENT_POSITION_FOLLOWING: number = Node.DOCUMENT_POSITION_FOLLOWING; - DOCUMENT_POSITION_PRECEDING: number = Node.DOCUMENT_POSITION_PRECEDING; -} - -export class MockAttribute extends MockNode implements Attr { - - ownerElement: Element; - value: string; - name: string; - // MSAttrExtensions - expando: boolean; - - constructor(name:string) { - super(name); - this.name = name; - this.expando = false; - } - - public get specified(): boolean { - return !!this.value; - } -} - -export interface ClientRect { - left: number; - width: number; - right: number; - top: number; - bottom: number; - height: number; -} - -export class MockElement extends MockNode implements Element { - // Added to make compiler happy. No real mocking - classList: DOMTokenList; - id: string; - className: string; - - scrollTop: number; - clientLeft: number; - scrollLeft: number; - tagName: string; - clientWidth: number; - scrollWidth: number; - clientHeight: number; - clientTop: number; - scrollHeight: number; - - constructor(tagName: string) { - super(tagName); - this.tagName = tagName; - } - - getAttribute(name?: string): string { - var filter = this._attributes.filter((attr) => { - return attr.name === name; - }); - - return filter.length ? filter[0].value : ''; - } - - get innerHTML(): string { - throw new Error('Not implemented!'); - } - - set innerHTML(value: string) { - throw new Error('Not implemented!'); - } - - getElementsByTagNameNS(namespaceURI: string, localName: string): NodeListOf { - throw new Error('Not implemented!'); - } - getElementsByClassName(classNames: string): NodeListOf { - throw new Error('Not implemented!'); - } - hasAttributeNS(namespaceURI: string, localName: string): boolean { - throw new Error('Not implemented!'); - } - getBoundingClientRect(): ClientRect { - throw new Error('Not implemented!'); - } - getAttributeNS(namespaceURI: string, localName: string): string { - throw new Error('Not implemented!'); - } - getAttributeNodeNS(namespaceURI: string, localName: string): Attr { - throw new Error('Not implemented!'); - } - setAttributeNodeNS(newAttr: Attr): Attr { - throw new Error('Not implemented!'); - } - hasAttribute(name: string): boolean { - var filter = this._attributes.filter((attr) => { - return attr.name === name; - }); - - return filter.length > 0; - } - removeAttribute(name?: string): void { - this._attributes = this._attributes.filter((attr) => { - return attr.name !== name; - }); - } - setAttributeNS(namespaceURI: string, qualifiedName: string, value: string): void { - throw new Error('Not implemented!'); - } - getAttributeNode(name: string): Attr { - throw new Error('Not implemented!'); - } - getElementsByTagName(name: string): NodeListOf { - throw new Error('Not implemented!'); - } - setAttributeNode(newAttr: Attr): Attr { - throw new Error('Not implemented!'); - } - getClientRects(): ClientRectList { - throw new Error('Not implemented!'); - } - removeAttributeNode(oldAttr: Attr): Attr { - throw new Error('Not implemented!'); - } - setAttribute(name?: string, value?: string): void { - if(this.hasAttribute(name)) { - this.removeAttribute(name); - } - var attr = this.ownerDocument.createAttribute(name); - attr.ownerElement = this; - attr.value = value; - this._attributes.push(attr); - } - removeAttributeNS(namespaceURI: string, localName: string): void { - throw new Error('Not implemented!'); - } - - matches(selector: string): boolean { - throw new Error('Not implemented!'); - } - - // interface NodeSelector - querySelectorAll(selectors: string): NodeListOf { - throw new Error('Not implemented!'); - } - querySelector(selectors: string): Element { - throw new Error('Not implemented!'); - } - - // interface ElementTraversal - public get childElementCount(): number { - return this._childNodes.filter((node) => { - return node.nodeType === this.ELEMENT_NODE; - }).length; - } - previousElementSibling: Element; - public get lastElementChild(): Element { - var a = this._childNodes.filter((node) => { - return node.nodeType === this.ELEMENT_NODE; - }); - return a[a.length - 1]; - } - nextElementSibling: Element; - public get firstElementChild(): Element { - var a = this._childNodes.filter((node) => { - return node.nodeType === this.ELEMENT_NODE; - }); - return a[0]; - } - - // interface MSElementExtensions - msMatchesSelector(selectors: string): boolean { - throw new Error('Not implemented!'); - } - fireEvent(eventName: string, eventObj?: any): boolean { - throw new Error('Not implemented!'); - } - // other interface msElementExtensions - msZoomTo(args: any) {} - msRequestFullscreen() {} - msGetUntransformedBounds():ClientRect { - throw new Error('Not implemented!'); - } - msRegionOverflow: string; - - requestFullscreen(): void { throw new Error('Not implemented!'); } - requestPointerLock(): void { throw new Error('Not implemented!'); } - - webkitMatchesSelector(selectors: string): boolean { throw new Error('Not implemented!'); } - webkitRequestFullScreen(): void { throw new Error('Not implemented!'); } - webkitRequestFullscreen(): void { throw new Error('Not implemented!'); } - - remove(): void { throw new Error('Not implemented!'); } - - onariarequest: (ev: any) => any; - oncommand: (ev: any) => any; - // Pointer events new in IE 11 - onlostpointercapture: (ev: any) => any; - ongotpointercapture: (ev: any) => any; - setPointerCapture: (ev: any) => any; - releasePointerCapture: (ev: any) => any; - onpointerenter: (ev: any) => any; - onpointerout: (ev: any) => any; - onpointerdown: (ev: any) => any; - onpointerup: (ev: any) => any; - onpointercancel: (ev: any) => any; - onpointerover: (ev: any) => any; - onpointermove: (ev: any) => any; - onpointerleave: (ev: any) => any; - - onwheel: (ev: any) => any; - - ontouchcancel: (ev: any) => any; - ontouchend: (ev: any) => any; - ontouchmove: (ev: any) => any; - ontouchstart: (ev: any) => any; - - onmspointerenter: (ev:any) => any; - onmspointerleave: (ev:any) => any; - onmspointerdown: (ev: any) => any; - onmsgotpointercapture: (ev: any) => any; - onmsgesturedoubletap: (ev: any) => any; - onmspointerhover: (ev: any) => any; - onmsgesturehold: (ev: any) => any; - onmspointermove: (ev: any) => any; - onmsgesturechange: (ev: any) => any; - onmsgesturestart: (ev: any) => any; - onmspointercancel: (ev: any) => any; - onmsgestureend: (ev: any) => any; - onmsgesturetap: (ev: any) => any; - onmspointerout: (ev: any) => any; - onmsinertiastart: (ev: any) => any; - onmslostpointercapture: (ev: any) => any; - onmspointerover: (ev: any) => any; - msContentZoomFactor: number; - onmspointerup: (ev: any) => any; - - onwebkitfullscreenchange: (ev: Event) => any; - onwebkitfullscreenerror: (ev: Event) => any; - - msGetRegionContent(): MSRangeCollection { - throw new Error('Not implemented!'); - } - msReleasePointerCapture(pointerId: number): void { - throw new Error('Not implemented!'); - } - msSetPointerCapture(pointerId: number): void { - throw new Error('Not implemented!'); - } -} - -export class MockCharacterData extends MockNode implements CharacterData { - length: number; - data: string; - - constructor(text:string) { - super(text); - this.nodeType = this.TEXT_NODE; - this.length = text.length; - this.data = text; - } - - deleteData(offset: number, count: number): void { - throw new Error('Not implemented!'); - } - replaceData(offset: number, count: number, arg: string): void { - throw new Error('Not implemented!'); - } - appendData(arg: string): void { - throw new Error('Not implemented!'); - } - insertData(offset: number, arg: string): void { - throw new Error('Not implemented!'); - } - substringData(offset: number, count: number): string { - throw new Error('Not implemented!'); - } - remove(): void { throw new Error('Not implemented!'); } -} - -export class MockText extends MockCharacterData implements Text { - wholeText: string; - - constructor(text:string) { - super(text); - this.wholeText = text; - } - - splitText(offset: number): Text { - throw new Error('Not implemented!'); - } - replaceWholeText(content: string): Text { - throw new Error('Not implemented!'); - } - swapNode(otherNode: Node): Node { - throw new Error('Not implemented!'); - } - removeNode(deep?: boolean): Node { - throw new Error('Not implemented!'); - } - replaceNode(replacement: Node): Node { - throw new Error('Not implemented!'); - } -} - -export class MockHTMLElement extends MockElement /* implements HTMLElement */ { - - public style: CSSStyleDeclaration; - - constructor(tagName: string) { - super(tagName); - this.style = {}; - this.nodeType = this.ELEMENT_NODE; - } - - public get className(): string { - return this.getAttribute('class'); - } - - public set className(value:string) { - this.setAttribute('class', value); - } - - public get id():string { - return this.getAttribute('id'); - } - - public set id(value:string) { - this.setAttribute('id', value); - } - - public get children(): HTMLCollection { - var a = this._childNodes.filter((node) => { - return node.nodeType === this.ELEMENT_NODE; - }); - if(!a.item) { - a.item = (function(index:number) { - return this[index]; - }).bind(a); - } - return a; - } - - get outerHTML(): string { - var stringer = new DOMStringer(this); - return stringer.toString(true); - } - - get innerHTML(): string { - var stringer = new DOMStringer(this); - return stringer.toString(); - } - - set innerHTML(value:string) { - var parser = new DOMParser(this.ownerDocument); - var nodes = parser.parse(value); - nodes.forEach((node) => { - this.appendChild(node); - }); - } -} - -export class MockDocument extends MockEventTarget /*implements Document*/ { - public createElement(tagName: string): HTMLElement { - var e = new MockHTMLElement(tagName); - e.ownerDocument = this; - return e; - } - public createTextNode(data: string): Text { - var n = new MockText(data); - n.ownerDocument = this; - return n; - } - public createAttribute(name: string): Attr { - var a = new MockAttribute(name); - a.ownerDocument = this; - return a; - } -} - -export class MockWindow /*implements Window*/ { - -} - -interface IParserState { - name: string; - consumeCharacter(stream:StringStream):IParserState; - onTransition(parser:DOMParser, nextState:string):void; - -} - -class ErrorState implements IParserState { - public name: string; - public message:string; - - constructor(message:string) { - this.name = 'error'; - this.message = message; - } - - consumeCharacter(stream:StringStream):IParserState { - return this; - } - - onTransition(parser:DOMParser, nextState:string):void { - - } -} - -class TextParser implements IParserState { - - public name: string; - private textContent: string; - - constructor() { - this.name = 'text'; - this.textContent = ''; - } - - consumeCharacter(stream:StringStream):IParserState { - var char = stream.next(); - switch(char) { - case '<': - return new TagParser(); - case '>': - return new ErrorState('Unexpected >'); - default: - this.textContent += char; - return this; - } - } - - onTransition(parser:DOMParser, nextState:string):void { - if(this.textContent) { - var node = parser.document.createTextNode(this.textContent); - if(parser.currentNode) { - parser.currentNode.appendChild(node); - } else { - parser.root.push(node); - } - } - } -} - -interface IMap { - [name: string]:string; -} - -class TagParser implements IParserState { - - public name: string; - private isClosing:boolean; - private tagName:string; - public attributes: IMap; - - constructor() { - this.name = 'tag'; - this.tagName = ''; - this.isClosing = false; - this.attributes = {}; - } - - consumeCharacter(stream:StringStream):IParserState { - var char = stream.next(); - switch(char) { - case '/': - this.isClosing = true; - return this; - case '>': - if(this.tagName) { - return new TextParser(); - } - else { - return new ErrorState('No tag name specified'); - } - case ' ': - if(this.tagName) { - if(this.isClosing) { - return new ErrorState('Closing tags cannot have attributes'); - } - return new AttributeParser(this); - } else { - return new ErrorState('Tag name must be first.'); - } - default: - this.tagName += char; - return this; - } - } - - onTransition(parser:DOMParser, nextState:string):void { - if(this.tagName && nextState !== 'attribute') { - if(this.isClosing) { - if(parser.openElements[parser.openElements.length - 1].tagName !== this.tagName) { - throw new Error('Mismatched closing tag:' + this.tagName); - } else { - parser.openElements.pop(); - if(parser.openElements.length) { - parser.currentNode = parser.openElements[parser.openElements.length - 1]; - } else { - parser.currentNode = null; - } - } - } else { - var node = parser.document.createElement(this.tagName); - Object.keys(this.attributes).forEach((key) => { - node.setAttribute(key, this.attributes[key]); - }); - if(parser.currentNode) { - parser.currentNode.appendChild(node); - } else { - parser.root.push(node); - } - parser.openElements.push(node); - parser.currentNode = node; - } - } - } -} - -class AttributeParser implements IParserState { - public name: string; - private tag: TagParser; - private attributeName:string; - public attributeValue:string; - private inValue:boolean; - - constructor(tag: TagParser) { - this.name = 'attribute'; - this.tag = tag; - this.inValue = false; - this.attributeName = ''; - } - - consumeCharacter(stream:StringStream):IParserState { - var char = stream.next(); - switch(char) { - case ' ': - if(this.inValue) { - return this.tag; - } else { - return this; - } - case '=': - this.inValue = true; - return new AttributeValueParser(this); - case '>': - stream.back(); - return this.tag; - default: - if(this.inValue === false) { - this.attributeName += char; - } - return this; - - } - } - - onTransition(parser:DOMParser, nextState:string):void { - if(nextState !== 'attributeValue') { - this.tag.attributes[this.attributeName] = this.attributeValue; - } - } -} - -class AttributeValueParser implements IParserState { - public name: string; - private attribute: AttributeParser; - private value:string; - private quote:boolean; - - constructor(attribute:AttributeParser) { - this.name = 'attributeValue'; - this.attribute = attribute; - this.value = ''; - this.quote = false; - } - - consumeCharacter(stream:StringStream):IParserState { - var char = stream.next(); - switch(char) { - case '"': - if(this.quote === false) { - this.quote = true; - return this; - } - else { - return this.attribute; - } - default: - if(this.quote === false) { - return new ErrorState('Expected " character'); - } else { - this.value += char; - } - return this; - - } - } - - onTransition(parser:DOMParser, nextState:string):void { - this.attribute.attributeValue = this.value; - } -} - -class StringStream { - private text: string; - private index = 0; - - constructor(text:string) { - this.text = text; - } - - public more():boolean { - return this.index < this.text.length; - } - - public next():string { - - if(this.index >= this.text.length) { - throw new Error('Past end of string!'); - } - - return this.text[this.index++]; - } - - public back() { - this.index--; - } -} - -class DOMParser { - public activeState: IParserState; - public currentNode: Node; - public openElements: Element[]; - public root:Node[]; - public document:Document; - - constructor(document:Document) { - this.document = document; - this.root = []; - this.openElements = []; - this.currentNode = null; - this.activeState = new TextParser(); - } - - public parse(text:string):Node[] { - - var stream = new StringStream(text); - while(stream.more()) { - var nextState = this.activeState.consumeCharacter(stream); - if(nextState !== this.activeState) { - this.activeState.onTransition(this, nextState.name); - this.activeState = nextState; - } - } - - if(this.activeState.name === 'error') { - throw new Error(( this.activeState).message); - } - if(this.openElements.length !== 0) { - throw new Error('Elements not closed: ' + this.openElements.map((element) => { - return element.tagName; - }).join()); - } - return this.root; - } -} - -class DOMStringer { - - private root:Node; - - constructor(root:Node) { - this.root = root; - } - - - - private print(node:Node):string { - var result = ''; - switch(node.nodeType) { - case node.ELEMENT_NODE: - result += this.printElement(node); - break; - case node.TEXT_NODE: - result += this.printText(node); - break; - } - return result; - } - - private printChildren(node:Node):string { - var result = ''; - if(node.hasChildNodes()) { - for(var i = 0; i < node.childNodes.length; i++) { - result += this.print(node.childNodes.item(i)); - } - } - return result; - } - - private printElement(element:Element):string { - var result = ['<']; - result.push(element.tagName); - if(element.hasAttributes()) { - var attributes:Attr[] = element.attributes; - result.push(attributes.reduce((prev:string, current:Attr) => { - var attr = [prev, current.name]; - if(current.value) { - attr.push('="', current.value, '"'); - } - return attr.join(''); - }, ' ')); - } - result.push('>'); - result.push(this.printChildren(element)); - result.push(''); - return result.join(''); - } - - private printText(text:Text):string { - return text.wholeText; - } - - public toString(includeRoot?:boolean):string { - if(includeRoot) { - return this.print(this.root); - } else { - return this.printChildren(this.root); - } - } -} \ No newline at end of file From 40be8b9649020b07438c5b019c8c729d624c5990 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 6 May 2016 12:25:25 +0200 Subject: [PATCH 077/297] Improve editor options handling --- src/vs/editor/browser/config/configuration.ts | 18 +- .../common/config/commonEditorConfig.ts | 53 +---- src/vs/editor/common/editorCommon.ts | 44 ++-- .../common/viewLayout/editorLayoutProvider.ts | 199 ++++++++++++------ .../test/common/mocks/mockConfiguration.ts | 10 +- 5 files changed, 194 insertions(+), 130 deletions(-) diff --git a/src/vs/editor/browser/config/configuration.ts b/src/vs/editor/browser/config/configuration.ts index 2d004b4fb42..ffdeefebfb4 100644 --- a/src/vs/editor/browser/config/configuration.ts +++ b/src/vs/editor/browser/config/configuration.ts @@ -207,15 +207,15 @@ class CSSBasedConfiguration extends Disposable { maxDigitWidth = Math.max(maxDigitWidth, digits[i].width); } - return new FontInfo( - bareFontInfo.fontFamily, - bareFontInfo.fontSize, - bareFontInfo.lineHeight, - typicalHalfwidthCharacter.width, - typicalFullwidthCharacter.width, - space.width, - maxDigitWidth - ); + return new FontInfo({ + fontFamily: bareFontInfo.fontFamily, + fontSize: bareFontInfo.fontSize, + lineHeight: bareFontInfo.lineHeight, + typicalHalfwidthCharacterWidth: typicalHalfwidthCharacter.width, + typicalFullwidthCharacterWidth: typicalFullwidthCharacter.width, + spaceWidth: space.width, + maxDigitWidth: maxDigitWidth + }); } } diff --git a/src/vs/editor/common/config/commonEditorConfig.ts b/src/vs/editor/common/config/commonEditorConfig.ts index dd4e6b5f558..28835b01079 100644 --- a/src/vs/editor/common/config/commonEditorConfig.ts +++ b/src/vs/editor/common/config/commonEditorConfig.ts @@ -13,7 +13,7 @@ import {Extensions, IConfigurationRegistry, IConfigurationNode} from 'vs/platfor import {Registry} from 'vs/platform/platform'; import {DefaultConfig, DEFAULT_INDENTATION, GOLDEN_LINE_HEIGHT_RATIO} from 'vs/editor/common/config/defaultConfig'; import * as editorCommon from 'vs/editor/common/editorCommon'; -import {EditorLayoutProvider} from 'vs/editor/common/viewLayout/editorLayoutProvider'; +import {EditorLayoutProvider, EditorLayoutInfo} from 'vs/editor/common/viewLayout/editorLayoutProvider'; /** * Experimental screen reader support toggle @@ -109,7 +109,7 @@ export class InternalEditorOptions implements editorCommon.IInternalEditorOption indentGuides: boolean; useTabStops: boolean; trimAutoWhitespace: boolean; - layoutInfo: editorCommon.IEditorLayoutInfo; + layoutInfo: EditorLayoutInfo; fontInfo: editorCommon.FontInfo; editorClassName: string; wrappingInfo: editorCommon.IEditorWrappingInfo; @@ -177,39 +177,8 @@ export class InternalEditorOptions implements editorCommon.IInternalEditorOption this.indentGuides = Boolean(input.indentGuides); this.useTabStops = Boolean(input.useTabStops); this.trimAutoWhitespace = Boolean(input.trimAutoWhitespace); - this.layoutInfo = { - width: Number(input.layoutInfo.width)|0, - height: Number(input.layoutInfo.height)|0, - glyphMarginLeft: Number(input.layoutInfo.glyphMarginLeft)|0, - glyphMarginWidth: Number(input.layoutInfo.glyphMarginWidth)|0, - glyphMarginHeight: Number(input.layoutInfo.glyphMarginHeight)|0, - lineNumbersLeft: Number(input.layoutInfo.lineNumbersLeft)|0, - lineNumbersWidth: Number(input.layoutInfo.lineNumbersWidth)|0, - lineNumbersHeight: Number(input.layoutInfo.lineNumbersHeight)|0, - decorationsLeft: Number(input.layoutInfo.decorationsLeft)|0, - decorationsWidth: Number(input.layoutInfo.decorationsWidth)|0, - decorationsHeight: Number(input.layoutInfo.decorationsHeight)|0, - contentLeft: Number(input.layoutInfo.contentLeft)|0, - contentWidth: Number(input.layoutInfo.contentWidth)|0, - contentHeight: Number(input.layoutInfo.contentHeight)|0, - verticalScrollbarWidth: Number(input.layoutInfo.verticalScrollbarWidth)|0, - horizontalScrollbarHeight: Number(input.layoutInfo.horizontalScrollbarHeight)|0, - overviewRuler:{ - width: Number(input.layoutInfo.overviewRuler.width)|0, - height: Number(input.layoutInfo.overviewRuler.height)|0, - top: Number(input.layoutInfo.overviewRuler.top)|0, - right: Number(input.layoutInfo.overviewRuler.right)|0, - } - }; - this.fontInfo = new editorCommon.FontInfo( - input.fontInfo.fontFamily, - input.fontInfo.fontSize, - input.fontInfo.lineHeight, - input.fontInfo.typicalHalfwidthCharacterWidth, - input.fontInfo.typicalFullwidthCharacterWidth, - input.fontInfo.spaceWidth, - input.fontInfo.maxDigitWidth - ); + this.layoutInfo = new EditorLayoutInfo(input.layoutInfo); + this.fontInfo = input.fontInfo.clone(); this.editorClassName = input.editorClassName; this.wrappingInfo = { isViewportWrapping: Boolean(input.wrappingInfo.isViewportWrapping), @@ -403,7 +372,7 @@ class InternalEditorOptionsHelper { }; } - public static createConfigurationChangedEvent(prevOpts:editorCommon.IInternalEditorOptions, newOpts:editorCommon.IInternalEditorOptions): editorCommon.IConfigurationChangedEvent { + public static createConfigurationChangedEvent(prevOpts:InternalEditorOptions, newOpts:InternalEditorOptions): editorCommon.IConfigurationChangedEvent { return { experimentalScreenReader: (prevOpts.experimentalScreenReader !== newOpts.experimentalScreenReader), rulers: (!this._numberArraysEqual(prevOpts.rulers, newOpts.rulers)), @@ -452,7 +421,7 @@ class InternalEditorOptionsHelper { useTabStops: (prevOpts.useTabStops !== newOpts.useTabStops), trimAutoWhitespace: (prevOpts.trimAutoWhitespace !== newOpts.trimAutoWhitespace), - layoutInfo: (!EditorLayoutProvider.layoutEqual(prevOpts.layoutInfo, newOpts.layoutInfo)), + layoutInfo: (!prevOpts.layoutInfo.equals(newOpts.layoutInfo)), fontInfo: (!prevOpts.fontInfo.equals(newOpts.fontInfo)), editorClassName: (prevOpts.editorClassName !== newOpts.editorClassName), wrappingInfo: (!this._wrappingInfoEqual(prevOpts.wrappingInfo, newOpts.wrappingInfo)), @@ -666,11 +635,11 @@ export abstract class CommonEditorConfiguration extends Disposable implements ed this.getOuterWidth(), this.getOuterHeight(), opts, - this.readConfiguration(new editorCommon.BareFontInfo( - fontFamily, - fontSize, - lineHeight - )), + this.readConfiguration(new editorCommon.BareFontInfo({ + fontFamily: fontFamily, + fontSize: fontSize, + lineHeight: lineHeight + })), editorClassName, this._isDominatedByLongLines, this._lineCount diff --git a/src/vs/editor/common/editorCommon.ts b/src/vs/editor/common/editorCommon.ts index c58a28dfafa..a5a7dd8f3ca 100644 --- a/src/vs/editor/common/editorCommon.ts +++ b/src/vs/editor/common/editorCommon.ts @@ -2407,10 +2407,14 @@ export class BareFontInfo { fontSize: number; lineHeight: number; - constructor(fontFamily: string, fontSize: number, lineHeight: number) { - this.fontFamily = String(fontFamily); - this.fontSize = fontSize|0; - this.lineHeight = lineHeight|0; + constructor(opts: { + fontFamily: string; + fontSize: number; + lineHeight: number; + }) { + this.fontFamily = String(opts.fontFamily); + this.fontSize = opts.fontSize|0; + this.lineHeight = opts.lineHeight|0; } public getId(): string { @@ -2426,20 +2430,20 @@ export class FontInfo extends BareFontInfo { spaceWidth:number; maxDigitWidth: number; - constructor( - fontFamily: string, - fontSize: number, - lineHeight: number, - typicalHalfwidthCharacterWidth:number, - typicalFullwidthCharacterWidth:number, - spaceWidth:number, - maxDigitWidth: number - ) { - super(fontFamily, fontSize, lineHeight); - this.typicalHalfwidthCharacterWidth = typicalHalfwidthCharacterWidth; - this.typicalFullwidthCharacterWidth = typicalFullwidthCharacterWidth; - this.spaceWidth = spaceWidth; - this.maxDigitWidth = maxDigitWidth; + constructor(opts:{ + fontFamily: string; + fontSize: number; + lineHeight: number; + typicalHalfwidthCharacterWidth:number; + typicalFullwidthCharacterWidth:number; + spaceWidth:number; + maxDigitWidth: number; + }) { + super(opts); + this.typicalHalfwidthCharacterWidth = opts.typicalHalfwidthCharacterWidth; + this.typicalFullwidthCharacterWidth = opts.typicalFullwidthCharacterWidth; + this.spaceWidth = opts.spaceWidth; + this.maxDigitWidth = opts.maxDigitWidth; } public equals(other:FontInfo): boolean { @@ -2453,6 +2457,10 @@ export class FontInfo extends BareFontInfo { && this.maxDigitWidth === other.maxDigitWidth ); } + + public clone(): FontInfo { + return new FontInfo(this); + } } export interface IConfiguration { diff --git a/src/vs/editor/common/viewLayout/editorLayoutProvider.ts b/src/vs/editor/common/viewLayout/editorLayoutProvider.ts index ec2752c9922..0eb6c90715c 100644 --- a/src/vs/editor/common/viewLayout/editorLayoutProvider.ts +++ b/src/vs/editor/common/viewLayout/editorLayoutProvider.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import {IEditorLayoutInfo} from 'vs/editor/common/editorCommon'; +import {IEditorLayoutInfo, IOverviewRulerPosition} from 'vs/editor/common/editorCommon'; export interface IEditorLayoutProviderOpts { outerWidth:number; @@ -26,83 +26,170 @@ export interface IEditorLayoutProviderOpts { horizontalScrollbarHeight:number; } +export class OverviewRulerPosition implements IOverviewRulerPosition { + _overviewRulerPositionBrand: void; + + public width:number; + public height:number; + public top:number; + public right:number; + + constructor(source:IOverviewRulerPosition) { + this.width = source.width|0; + this.height = source.height|0; + this.top = source.top|0; + this.right = source.right|0; + } + + public equals(other:OverviewRulerPosition): boolean { + return ( + this.width === other.width + && this.height === other.height + && this.top === other.top + && this.right === other.right + ); + } + + public clone(): OverviewRulerPosition { + return new OverviewRulerPosition(this); + } +} + +export class EditorLayoutInfo implements IEditorLayoutInfo { + _editorLayoutInfoBrand: void; + + public width:number; + public height:number; + public glyphMarginLeft:number; + public glyphMarginWidth:number; + public glyphMarginHeight:number; + public lineNumbersLeft:number; + public lineNumbersWidth:number; + public lineNumbersHeight:number; + public decorationsLeft:number; + public decorationsWidth:number; + public decorationsHeight:number; + public contentLeft:number; + public contentWidth:number; + public contentHeight:number; + public verticalScrollbarWidth:number; + public horizontalScrollbarHeight:number; + public overviewRuler:OverviewRulerPosition; + + constructor(source:IEditorLayoutInfo) { + this.width = source.width|0; + this.height = source.height|0; + this.glyphMarginLeft = source.glyphMarginLeft|0; + this.glyphMarginWidth = source.glyphMarginWidth|0; + this.glyphMarginHeight = source.glyphMarginHeight|0; + this.lineNumbersLeft = source.lineNumbersLeft|0; + this.lineNumbersWidth = source.lineNumbersWidth|0; + this.lineNumbersHeight = source.lineNumbersHeight|0; + this.decorationsLeft = source.decorationsLeft|0; + this.decorationsWidth = source.decorationsWidth|0; + this.decorationsHeight = source.decorationsHeight|0; + this.contentLeft = source.contentLeft|0; + this.contentWidth = source.contentWidth|0; + this.contentHeight = source.contentHeight|0; + this.verticalScrollbarWidth = source.verticalScrollbarWidth|0; + this.horizontalScrollbarHeight = source.horizontalScrollbarHeight|0; + this.overviewRuler = new OverviewRulerPosition(source.overviewRuler); + } + + public equals(other:EditorLayoutInfo): boolean { + return ( + this.width === other.width + && this.height === other.height + && this.glyphMarginLeft === other.glyphMarginLeft + && this.glyphMarginWidth === other.glyphMarginWidth + && this.glyphMarginHeight === other.glyphMarginHeight + && this.lineNumbersLeft === other.lineNumbersLeft + && this.lineNumbersWidth === other.lineNumbersWidth + && this.lineNumbersHeight === other.lineNumbersHeight + && this.decorationsLeft === other.decorationsLeft + && this.decorationsWidth === other.decorationsWidth + && this.decorationsHeight === other.decorationsHeight + && this.contentLeft === other.contentLeft + && this.contentWidth === other.contentWidth + && this.contentHeight === other.contentHeight + && this.verticalScrollbarWidth === other.verticalScrollbarWidth + && this.horizontalScrollbarHeight === other.horizontalScrollbarHeight + && this.overviewRuler.equals(other.overviewRuler) + ); + } + + public clone(): EditorLayoutInfo { + return new EditorLayoutInfo(this); + } +} + export class EditorLayoutProvider { - public static compute(opts:IEditorLayoutProviderOpts): IEditorLayoutInfo { - let lineNumbersWidth = this.computeLineNumbersWidth(opts); - let glyphMarginWidth = this.computeGlyphMarginWidth(opts); + public static compute(_opts:IEditorLayoutProviderOpts): EditorLayoutInfo { + const outerWidth = _opts.outerWidth|0; + const outerHeight = _opts.outerHeight|0; + const showGlyphMargin = Boolean(_opts.showGlyphMargin); + const lineHeight = _opts.lineHeight|0; + const showLineNumbers = Boolean(_opts.showLineNumbers); + const lineNumbersMinChars = _opts.lineNumbersMinChars|0; + const lineDecorationsWidth = _opts.lineDecorationsWidth|0; + const maxDigitWidth = Number(_opts.maxDigitWidth); + const lineCount = _opts.lineCount|0; + const verticalScrollbarWidth = _opts.verticalScrollbarWidth|0; + const verticalScrollbarHasArrows = Boolean(_opts.verticalScrollbarHasArrows); + const scrollbarArrowSize = _opts.scrollbarArrowSize|0; + const horizontalScrollbarHeight = _opts.horizontalScrollbarHeight|0; - let contentWidth = opts.outerWidth - glyphMarginWidth - lineNumbersWidth - opts.lineDecorationsWidth; + let lineNumbersWidth = 0; + if (showLineNumbers) { + let digitCount = Math.max(this.digitCount(lineCount), lineNumbersMinChars); + lineNumbersWidth = Math.round(digitCount * maxDigitWidth); + } + + let glyphMarginWidth = 0; + if (showGlyphMargin) { + glyphMarginWidth = lineHeight; + } + + let contentWidth = outerWidth - glyphMarginWidth - lineNumbersWidth - lineDecorationsWidth; let glyphMarginLeft = 0; let lineNumbersLeft = glyphMarginLeft + glyphMarginWidth; let decorationsLeft = lineNumbersLeft + lineNumbersWidth; - let contentLeft = decorationsLeft + opts.lineDecorationsWidth; + let contentLeft = decorationsLeft + lineDecorationsWidth; - let verticalArrowSize = (opts.verticalScrollbarHasArrows ? opts.scrollbarArrowSize : 0); + let verticalArrowSize = (verticalScrollbarHasArrows ? scrollbarArrowSize : 0); - return { - width: opts.outerWidth, - height: opts.outerHeight, + return new EditorLayoutInfo({ + width: outerWidth, + height: outerHeight, glyphMarginLeft: glyphMarginLeft, glyphMarginWidth: glyphMarginWidth, - glyphMarginHeight: opts.outerHeight, + glyphMarginHeight: outerHeight, lineNumbersLeft: lineNumbersLeft, lineNumbersWidth: lineNumbersWidth, - lineNumbersHeight: opts.outerHeight, + lineNumbersHeight: outerHeight, decorationsLeft: decorationsLeft, - decorationsWidth: opts.lineDecorationsWidth, - decorationsHeight: opts.outerHeight, + decorationsWidth: lineDecorationsWidth, + decorationsHeight: outerHeight, contentLeft: contentLeft, contentWidth: contentWidth, - contentHeight: opts.outerHeight, + contentHeight: outerHeight, - verticalScrollbarWidth: opts.verticalScrollbarWidth, - horizontalScrollbarHeight: opts.horizontalScrollbarHeight, + verticalScrollbarWidth: verticalScrollbarWidth, + horizontalScrollbarHeight: horizontalScrollbarHeight, overviewRuler: { top: verticalArrowSize, - width: opts.verticalScrollbarWidth, - height: (opts.outerHeight - 2 * verticalArrowSize), + width: verticalScrollbarWidth, + height: (outerHeight - 2 * verticalArrowSize), right: 0 } - }; - } - - public static layoutEqual(a:IEditorLayoutInfo, b:IEditorLayoutInfo): boolean { - return ( - a.width === b.width - && a.height === b.height - && a.glyphMarginLeft === b.glyphMarginLeft - && a.glyphMarginWidth === b.glyphMarginWidth - && a.glyphMarginHeight === b.glyphMarginHeight - && a.lineNumbersLeft === b.lineNumbersLeft - && a.lineNumbersWidth === b.lineNumbersWidth - && a.lineNumbersHeight === b.lineNumbersHeight - && a.decorationsLeft === b.decorationsLeft - && a.decorationsWidth === b.decorationsWidth - && a.decorationsHeight === b.decorationsHeight - && a.contentLeft === b.contentLeft - && a.contentWidth === b.contentWidth - && a.contentHeight === b.contentHeight - && a.verticalScrollbarWidth === b.verticalScrollbarWidth - && a.horizontalScrollbarHeight === b.horizontalScrollbarHeight - && a.overviewRuler.top === b.overviewRuler.top - && a.overviewRuler.width === b.overviewRuler.width - && a.overviewRuler.height === b.overviewRuler.height - && a.overviewRuler.right === b.overviewRuler.right - ); - } - - private static computeGlyphMarginWidth(opts:IEditorLayoutProviderOpts): number { - if (opts.showGlyphMargin) { - return opts.lineHeight; - } - return 0; + }); } private static digitCount(n:number): number { @@ -113,12 +200,4 @@ export class EditorLayoutProvider { } return r ? r : 1; } - - private static computeLineNumbersWidth(opts:IEditorLayoutProviderOpts): number { - if (opts.showLineNumbers) { - var digitCount = Math.max(this.digitCount(opts.lineCount), opts.lineNumbersMinChars); - return Math.round(digitCount * opts.maxDigitWidth); - } - return 0; - } } diff --git a/src/vs/editor/test/common/mocks/mockConfiguration.ts b/src/vs/editor/test/common/mocks/mockConfiguration.ts index f6dd3b266df..ca45c98bf01 100644 --- a/src/vs/editor/test/common/mocks/mockConfiguration.ts +++ b/src/vs/editor/test/common/mocks/mockConfiguration.ts @@ -26,6 +26,14 @@ export class MockConfiguration extends CommonEditorConfiguration { } protected readConfiguration(styling: BareFontInfo): FontInfo { - return new FontInfo('mockFont', 14, 19, 10, 20, 10, 10); + return new FontInfo({ + fontFamily: 'mockFont', + fontSize: 14, + lineHeight: 19, + typicalHalfwidthCharacterWidth:10, + typicalFullwidthCharacterWidth:20, + spaceWidth:10, + maxDigitWidth: 10, + }); } } From 2d9d98c3649dd03c4a2f5384fffcf361c46f766b Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 6 May 2016 12:31:43 +0200 Subject: [PATCH 078/297] convert IOverviewRulerPosition to OverviewRulerPosition --- src/vs/editor/browser/editorBrowser.ts | 2 +- .../viewParts/overviewRuler/overviewRuler.ts | 4 +- .../overviewRuler/overviewRulerImpl.ts | 4 +- .../editor/browser/widget/diffEditorWidget.ts | 8 ++-- src/vs/editor/common/editorCommon.ts | 31 +++++++++++++- .../common/viewLayout/editorLayoutProvider.ts | 37 ++-------------- .../viewLayout/editorLayoutProvider.test.ts | 42 +++++++++---------- 7 files changed, 63 insertions(+), 65 deletions(-) diff --git a/src/vs/editor/browser/editorBrowser.ts b/src/vs/editor/browser/editorBrowser.ts index 745a733a67d..03951ce0f96 100644 --- a/src/vs/editor/browser/editorBrowser.ts +++ b/src/vs/editor/browser/editorBrowser.ts @@ -459,7 +459,7 @@ export interface IOverviewRuler { getDomNode(): HTMLElement; dispose(): void; setZones(zones:OverviewRulerZone[]): void; - setLayout(position:editorCommon.IOverviewRulerPosition): void; + setLayout(position:editorCommon.OverviewRulerPosition): void; } /** * A rich code editor. diff --git a/src/vs/editor/browser/viewParts/overviewRuler/overviewRuler.ts b/src/vs/editor/browser/viewParts/overviewRuler/overviewRuler.ts index 05ac93bdd80..b40acc4bb36 100644 --- a/src/vs/editor/browser/viewParts/overviewRuler/overviewRuler.ts +++ b/src/vs/editor/browser/viewParts/overviewRuler/overviewRuler.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import {IConfigurationChangedEvent, IOverviewRulerPosition, IScrollEvent} from 'vs/editor/common/editorCommon'; +import {IConfigurationChangedEvent, OverviewRulerPosition, IScrollEvent} from 'vs/editor/common/editorCommon'; import {ViewEventHandler} from 'vs/editor/common/viewModel/viewEventHandler'; import {IOverviewRuler, OverviewRulerZone} from 'vs/editor/browser/editorBrowser'; import {OverviewRulerImpl} from 'vs/editor/browser/viewParts/overviewRuler/overviewRulerImpl'; @@ -58,7 +58,7 @@ export class OverviewRuler extends ViewEventHandler implements IOverviewRuler { return this._overviewRuler.getDomNode(); } - public setLayout(position:IOverviewRulerPosition): void { + public setLayout(position:OverviewRulerPosition): void { this._overviewRuler.setLayout(position, true); } diff --git a/src/vs/editor/browser/viewParts/overviewRuler/overviewRulerImpl.ts b/src/vs/editor/browser/viewParts/overviewRuler/overviewRulerImpl.ts index 7f973313cba..131cdb3503f 100644 --- a/src/vs/editor/browser/viewParts/overviewRuler/overviewRulerImpl.ts +++ b/src/vs/editor/browser/viewParts/overviewRuler/overviewRulerImpl.ts @@ -6,7 +6,7 @@ import * as browser from 'vs/base/browser/browser'; import {StyleMutator} from 'vs/base/browser/styleMutator'; -import {IOverviewRulerPosition, OverviewRulerLane} from 'vs/editor/common/editorCommon'; +import {OverviewRulerPosition, OverviewRulerLane} from 'vs/editor/common/editorCommon'; import {OverviewRulerZone, ColorZone} from 'vs/editor/browser/editorBrowser'; class ZoneManager { @@ -302,7 +302,7 @@ export class OverviewRulerImpl { this._zoneManager = null; } - public setLayout(position:IOverviewRulerPosition, render:boolean): void { + public setLayout(position:OverviewRulerPosition, render:boolean): void { StyleMutator.setTop(this._domNode, position.top); StyleMutator.setRight(this._domNode, position.right); diff --git a/src/vs/editor/browser/widget/diffEditorWidget.ts b/src/vs/editor/browser/widget/diffEditorWidget.ts index def99b7dcd6..08de0c5863c 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget.ts @@ -653,18 +653,18 @@ export class DiffEditorWidget extends EventEmitter implements editorBrowser.IDif var freeSpace = DiffEditorWidget.ENTIRE_DIFF_OVERVIEW_WIDTH - 2*DiffEditorWidget.ONE_OVERVIEW_WIDTH; var layoutInfo = this.modifiedEditor.getLayoutInfo(); if (layoutInfo) { - this._originalOverviewRuler.setLayout({ + this._originalOverviewRuler.setLayout(new editorCommon.OverviewRulerPosition({ top: 0, width: DiffEditorWidget.ONE_OVERVIEW_WIDTH, right: freeSpace + DiffEditorWidget.ONE_OVERVIEW_WIDTH, height: this._height - }); - this._modifiedOverviewRuler.setLayout({ + })); + this._modifiedOverviewRuler.setLayout(new editorCommon.OverviewRulerPosition({ top: 0, right: 0, width: DiffEditorWidget.ONE_OVERVIEW_WIDTH, height: this._height - }); + })); } } diff --git a/src/vs/editor/common/editorCommon.ts b/src/vs/editor/common/editorCommon.ts index a5a7dd8f3ca..d2113fcbdd0 100644 --- a/src/vs/editor/common/editorCommon.ts +++ b/src/vs/editor/common/editorCommon.ts @@ -2106,7 +2106,9 @@ export interface IEditorWhitespace { /** * A description for the overview ruler position. */ -export interface IOverviewRulerPosition { +export class OverviewRulerPosition { + _overviewRulerPositionBrand: void; + /** * Width of the overview ruler */ @@ -2123,6 +2125,31 @@ export interface IOverviewRulerPosition { * Right position for the overview ruler */ right:number; + + constructor(source:{ + width:number; + height:number; + top:number; + right:number; + }) { + this.width = source.width|0; + this.height = source.height|0; + this.top = source.top|0; + this.right = source.right|0; + } + + public equals(other:OverviewRulerPosition): boolean { + return ( + this.width === other.width + && this.height === other.height + && this.top === other.top + && this.right === other.right + ); + } + + public clone(): OverviewRulerPosition { + return new OverviewRulerPosition(this); + } } /** @@ -2202,7 +2229,7 @@ export interface IEditorLayoutInfo { /** * The position of the overview ruler. */ - overviewRuler:IOverviewRulerPosition; + overviewRuler:OverviewRulerPosition; } /** diff --git a/src/vs/editor/common/viewLayout/editorLayoutProvider.ts b/src/vs/editor/common/viewLayout/editorLayoutProvider.ts index 0eb6c90715c..8ae69ae9f84 100644 --- a/src/vs/editor/common/viewLayout/editorLayoutProvider.ts +++ b/src/vs/editor/common/viewLayout/editorLayoutProvider.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import {IEditorLayoutInfo, IOverviewRulerPosition} from 'vs/editor/common/editorCommon'; +import {IEditorLayoutInfo, OverviewRulerPosition} from 'vs/editor/common/editorCommon'; export interface IEditorLayoutProviderOpts { outerWidth:number; @@ -26,35 +26,6 @@ export interface IEditorLayoutProviderOpts { horizontalScrollbarHeight:number; } -export class OverviewRulerPosition implements IOverviewRulerPosition { - _overviewRulerPositionBrand: void; - - public width:number; - public height:number; - public top:number; - public right:number; - - constructor(source:IOverviewRulerPosition) { - this.width = source.width|0; - this.height = source.height|0; - this.top = source.top|0; - this.right = source.right|0; - } - - public equals(other:OverviewRulerPosition): boolean { - return ( - this.width === other.width - && this.height === other.height - && this.top === other.top - && this.right === other.right - ); - } - - public clone(): OverviewRulerPosition { - return new OverviewRulerPosition(this); - } -} - export class EditorLayoutInfo implements IEditorLayoutInfo { _editorLayoutInfoBrand: void; @@ -93,7 +64,7 @@ export class EditorLayoutInfo implements IEditorLayoutInfo { this.contentHeight = source.contentHeight|0; this.verticalScrollbarWidth = source.verticalScrollbarWidth|0; this.horizontalScrollbarHeight = source.horizontalScrollbarHeight|0; - this.overviewRuler = new OverviewRulerPosition(source.overviewRuler); + this.overviewRuler = source.overviewRuler.clone(); } public equals(other:EditorLayoutInfo): boolean { @@ -183,12 +154,12 @@ export class EditorLayoutProvider { verticalScrollbarWidth: verticalScrollbarWidth, horizontalScrollbarHeight: horizontalScrollbarHeight, - overviewRuler: { + overviewRuler: new OverviewRulerPosition({ top: verticalArrowSize, width: verticalScrollbarWidth, height: (outerHeight - 2 * verticalArrowSize), right: 0 - } + }) }); } diff --git a/src/vs/editor/test/common/viewLayout/editorLayoutProvider.test.ts b/src/vs/editor/test/common/viewLayout/editorLayoutProvider.test.ts index bf681fcbb45..d45f132e463 100644 --- a/src/vs/editor/test/common/viewLayout/editorLayoutProvider.test.ts +++ b/src/vs/editor/test/common/viewLayout/editorLayoutProvider.test.ts @@ -5,7 +5,7 @@ 'use strict'; import * as assert from 'assert'; -import {IEditorLayoutInfo} from 'vs/editor/common/editorCommon'; +import {IEditorLayoutInfo, OverviewRulerPosition} from 'vs/editor/common/editorCommon'; import {EditorLayoutProvider, IEditorLayoutProviderOpts} from 'vs/editor/common/viewLayout/editorLayoutProvider'; suite('Editor ViewLayout - EditorLayoutProvider', () => { @@ -53,12 +53,12 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { verticalScrollbarWidth: 0, horizontalScrollbarHeight: 0, - overviewRuler: { + overviewRuler: new OverviewRulerPosition({ top: 0, width: 0, height: 800, right: 0 - } + }) }); }); @@ -100,12 +100,12 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { verticalScrollbarWidth: 11, horizontalScrollbarHeight: 12, - overviewRuler: { + overviewRuler: new OverviewRulerPosition({ top: 13, width: 11, height: (800 - 2 * 13), right: 0 - } + }) }); }); @@ -147,12 +147,12 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { verticalScrollbarWidth: 0, horizontalScrollbarHeight: 0, - overviewRuler: { + overviewRuler: new OverviewRulerPosition({ top: 0, width: 0, height: 800, right: 0 - } + }) }); }); @@ -194,12 +194,12 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { verticalScrollbarWidth: 0, horizontalScrollbarHeight: 0, - overviewRuler: { + overviewRuler: new OverviewRulerPosition({ top: 0, width: 0, height: 900, right: 0 - } + }) }); }); @@ -241,12 +241,12 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { verticalScrollbarWidth: 0, horizontalScrollbarHeight: 0, - overviewRuler: { + overviewRuler: new OverviewRulerPosition({ top: 0, width: 0, height: 900, right: 0 - } + }) }); }); @@ -288,12 +288,12 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { verticalScrollbarWidth: 0, horizontalScrollbarHeight: 0, - overviewRuler: { + overviewRuler: new OverviewRulerPosition({ top: 0, width: 0, height: 900, right: 0 - } + }) }); }); @@ -335,12 +335,12 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { verticalScrollbarWidth: 0, horizontalScrollbarHeight: 0, - overviewRuler: { + overviewRuler: new OverviewRulerPosition({ top: 0, width: 0, height: 900, right: 0 - } + }) }); }); @@ -382,12 +382,12 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { verticalScrollbarWidth: 0, horizontalScrollbarHeight: 0, - overviewRuler: { + overviewRuler: new OverviewRulerPosition({ top: 0, width: 0, height: 900, right: 0 - } + }) }); }); @@ -429,12 +429,12 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { verticalScrollbarWidth: 0, horizontalScrollbarHeight: 0, - overviewRuler: { + overviewRuler: new OverviewRulerPosition({ top: 0, width: 0, height: 900, right: 0 - } + }) }); }); @@ -476,12 +476,12 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { verticalScrollbarWidth: 0, horizontalScrollbarHeight: 0, - overviewRuler: { + overviewRuler: new OverviewRulerPosition({ top: 0, width: 0, height: 900, right: 0 - } + }) }); }); }); From c5eee87819b0d4cf46e124f530ef0165de222d5d Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 6 May 2016 12:38:31 +0200 Subject: [PATCH 079/297] Convert IEditorLayoutInfo to EditorLayoutInfo --- .../browser/controller/keyboardHandler.ts | 2 +- .../editor/browser/controller/mouseHandler.ts | 4 +- .../editor/browser/controller/mouseTarget.ts | 8 +-- src/vs/editor/browser/view/viewImpl.ts | 2 +- src/vs/editor/browser/view/viewLayer.ts | 2 +- src/vs/editor/browser/view/viewOverlays.ts | 4 +- .../contentWidgets/contentWidgets.ts | 2 +- .../currentLineHighlight.ts | 2 +- .../viewParts/decorations/decorations.ts | 2 +- .../viewParts/glyphMargin/glyphMargin.ts | 2 +- .../viewParts/lineNumbers/lineNumbers.ts | 2 +- .../browser/viewParts/lines/viewLines.ts | 2 +- .../linesDecorations/linesDecorations.ts | 2 +- .../overlayWidgets/overlayWidgets.ts | 4 +- .../overviewRuler/decorationsOverviewRuler.ts | 2 +- .../scrollDecoration/scrollDecoration.ts | 4 +- .../viewParts/selections/selections.ts | 2 +- .../viewParts/viewCursors/viewCursors.ts | 2 +- .../browser/viewParts/viewZones/viewZones.ts | 2 +- .../editor/browser/widget/diffEditorWidget.ts | 2 +- src/vs/editor/common/commonCodeEditor.ts | 2 +- .../common/config/commonEditorConfig.ts | 6 +- src/vs/editor/common/editorCommon.ts | 72 ++++++++++++++++++- .../common/viewLayout/editorLayoutProvider.ts | 71 +----------------- .../common/viewModel/viewEventHandler.ts | 4 +- .../contrib/zoneWidget/browser/zoneWidget.ts | 6 +- .../viewLayout/editorLayoutProvider.test.ts | 44 ++++++------ 27 files changed, 128 insertions(+), 131 deletions(-) diff --git a/src/vs/editor/browser/controller/keyboardHandler.ts b/src/vs/editor/browser/controller/keyboardHandler.ts index 459daff2a92..97598308345 100644 --- a/src/vs/editor/browser/controller/keyboardHandler.ts +++ b/src/vs/editor/browser/controller/keyboardHandler.ts @@ -357,7 +357,7 @@ export class KeyboardHandler extends ViewEventHandler implements IDisposable { return false; } - public onLayoutChanged(layoutInfo:editorCommon.IEditorLayoutInfo): boolean { + public onLayoutChanged(layoutInfo:editorCommon.EditorLayoutInfo): boolean { this.contentLeft = layoutInfo.contentLeft; this.contentWidth = layoutInfo.contentWidth; return false; diff --git a/src/vs/editor/browser/controller/mouseHandler.ts b/src/vs/editor/browser/controller/mouseHandler.ts index d8771acf293..90a9caef4ed 100644 --- a/src/vs/editor/browser/controller/mouseHandler.ts +++ b/src/vs/editor/browser/controller/mouseHandler.ts @@ -179,8 +179,8 @@ export class MouseHandler extends ViewEventHandler implements IDisposable { } // --- begin event handlers - _layoutInfo:editorCommon.IEditorLayoutInfo; - public onLayoutChanged(layoutInfo:editorCommon.IEditorLayoutInfo): boolean { + _layoutInfo:editorCommon.EditorLayoutInfo; + public onLayoutChanged(layoutInfo:editorCommon.EditorLayoutInfo): boolean { this._layoutInfo = layoutInfo; return false; } diff --git a/src/vs/editor/browser/controller/mouseTarget.ts b/src/vs/editor/browser/controller/mouseTarget.ts index e11b4a74e37..c2d0923506a 100644 --- a/src/vs/editor/browser/controller/mouseTarget.ts +++ b/src/vs/editor/browser/controller/mouseTarget.ts @@ -6,7 +6,7 @@ import {Position} from 'vs/editor/common/core/position'; import {Range as EditorRange} from 'vs/editor/common/core/range'; -import {IEditorLayoutInfo, IEditorPosition, IEditorRange, IPosition, MouseTargetType} from 'vs/editor/common/editorCommon'; +import {EditorLayoutInfo, IEditorPosition, IEditorRange, IPosition, MouseTargetType} from 'vs/editor/common/editorCommon'; import {ClassNames, IMouseTarget, IViewZoneData} from 'vs/editor/browser/editorBrowser'; import {IDomNodePosition} from 'vs/base/browser/dom'; import {ViewContext} from 'vs/editor/common/view/viewContext'; @@ -177,7 +177,7 @@ export class MouseTargetFactory { return false; } - public createMouseTarget(layoutInfo:IEditorLayoutInfo, editorContent:IDomNodePosition, e:ISimplifiedMouseEvent, testEventTarget:boolean): IMouseTarget { + public createMouseTarget(layoutInfo:EditorLayoutInfo, editorContent:IDomNodePosition, e:ISimplifiedMouseEvent, testEventTarget:boolean): IMouseTarget { try { var r = this._unsafeCreateMouseTarget(layoutInfo, editorContent, e, testEventTarget); return r; @@ -186,7 +186,7 @@ export class MouseTargetFactory { } } - private _unsafeCreateMouseTarget(layoutInfo:IEditorLayoutInfo, editorContent:IDomNodePosition, e:ISimplifiedMouseEvent, testEventTarget:boolean): IMouseTarget { + private _unsafeCreateMouseTarget(layoutInfo:EditorLayoutInfo, editorContent:IDomNodePosition, e:ISimplifiedMouseEvent, testEventTarget:boolean): IMouseTarget { var mouseVerticalOffset = Math.max(0, this._viewHelper.getScrollTop() + (e.posy - editorContent.top)); var mouseContentHorizontalOffset = this._viewHelper.getScrollLeft() + (e.posx - editorContent.left) - layoutInfo.contentLeft; let mouseColumn = this._getMouseColumn(mouseContentHorizontalOffset); @@ -594,7 +594,7 @@ export class MouseTargetFactory { }; } - public getMouseColumn(layoutInfo:IEditorLayoutInfo, editorContent:IDomNodePosition, e:ISimplifiedMouseEvent): number { + public getMouseColumn(layoutInfo:EditorLayoutInfo, editorContent:IDomNodePosition, e:ISimplifiedMouseEvent): number { let mouseContentHorizontalOffset = this._viewHelper.getScrollLeft() + (e.posx - editorContent.left) - layoutInfo.contentLeft; return this._getMouseColumn(mouseContentHorizontalOffset); } diff --git a/src/vs/editor/browser/view/viewImpl.ts b/src/vs/editor/browser/view/viewImpl.ts index a86d121979d..977b282def2 100644 --- a/src/vs/editor/browser/view/viewImpl.ts +++ b/src/vs/editor/browser/view/viewImpl.ts @@ -423,7 +423,7 @@ export class View extends ViewEventHandler implements editorBrowser.IView, IDisp // --- begin event handlers - public onLayoutChanged(layoutInfo:editorCommon.IEditorLayoutInfo): boolean { + public onLayoutChanged(layoutInfo:editorCommon.EditorLayoutInfo): boolean { if (browser.isChrome) { /* tslint:disable:no-unused-variable */ // Access overflowGuardContainer.clientWidth to prevent relayouting bug in Chrome diff --git a/src/vs/editor/browser/view/viewLayer.ts b/src/vs/editor/browser/view/viewLayer.ts index d222abfa8ee..fb01ddd9a9c 100644 --- a/src/vs/editor/browser/view/viewLayer.ts +++ b/src/vs/editor/browser/view/viewLayer.ts @@ -86,7 +86,7 @@ export abstract class ViewLayer extends ViewPart { return true; } - public onLayoutChanged(layoutInfo:editorCommon.IEditorLayoutInfo): boolean { + public onLayoutChanged(layoutInfo:editorCommon.EditorLayoutInfo): boolean { return true; } diff --git a/src/vs/editor/browser/view/viewOverlays.ts b/src/vs/editor/browser/view/viewOverlays.ts index 4bc5259443f..4e4959a9c89 100644 --- a/src/vs/editor/browser/view/viewOverlays.ts +++ b/src/vs/editor/browser/view/viewOverlays.ts @@ -6,7 +6,7 @@ import * as browser from 'vs/base/browser/browser'; import {StyleMutator, FastDomNode, createFastDomNode} from 'vs/base/browser/styleMutator'; -import {IScrollEvent, IConfigurationChangedEvent, IEditorLayoutInfo, IModelDecoration} from 'vs/editor/common/editorCommon'; +import {IScrollEvent, IConfigurationChangedEvent, EditorLayoutInfo, IModelDecoration} from 'vs/editor/common/editorCommon'; import * as editorBrowser from 'vs/editor/browser/editorBrowser'; import {IVisibleLineData, ViewLayer} from 'vs/editor/browser/view/viewLayer'; import {DynamicViewOverlay} from 'vs/editor/browser/view/dynamicViewOverlay'; @@ -262,7 +262,7 @@ export class MarginViewOverlays extends ViewOverlays { return super.onScrollChanged(e) || e.scrollHeightChanged; } - public onLayoutChanged(layoutInfo:IEditorLayoutInfo): boolean { + public onLayoutChanged(layoutInfo:EditorLayoutInfo): boolean { this._glyphMarginLeft = layoutInfo.glyphMarginLeft; this._glyphMarginWidth = layoutInfo.glyphMarginWidth; this._scrollHeight = this._layoutProvider.getScrollHeight(); diff --git a/src/vs/editor/browser/viewParts/contentWidgets/contentWidgets.ts b/src/vs/editor/browser/viewParts/contentWidgets/contentWidgets.ts index 12ba7c21ad5..d11d9a98327 100644 --- a/src/vs/editor/browser/viewParts/contentWidgets/contentWidgets.ts +++ b/src/vs/editor/browser/viewParts/contentWidgets/contentWidgets.ts @@ -111,7 +111,7 @@ export class ViewContentWidgets extends ViewPart { } return true; } - public onLayoutChanged(layoutInfo:editorCommon.IEditorLayoutInfo): boolean { + public onLayoutChanged(layoutInfo:editorCommon.EditorLayoutInfo): boolean { this._contentLeft = layoutInfo.contentLeft; if (this._contentWidth !== layoutInfo.contentWidth) { diff --git a/src/vs/editor/browser/viewParts/currentLineHighlight/currentLineHighlight.ts b/src/vs/editor/browser/viewParts/currentLineHighlight/currentLineHighlight.ts index 429f8e69719..4bc8c0b870f 100644 --- a/src/vs/editor/browser/viewParts/currentLineHighlight/currentLineHighlight.ts +++ b/src/vs/editor/browser/viewParts/currentLineHighlight/currentLineHighlight.ts @@ -87,7 +87,7 @@ export class CurrentLineHighlightOverlay extends DynamicViewOverlay { } return true; } - public onLayoutChanged(layoutInfo:editorCommon.IEditorLayoutInfo): boolean { + public onLayoutChanged(layoutInfo:editorCommon.EditorLayoutInfo): boolean { return true; } public onScrollChanged(e:editorCommon.IScrollEvent): boolean { diff --git a/src/vs/editor/browser/viewParts/decorations/decorations.ts b/src/vs/editor/browser/viewParts/decorations/decorations.ts index 5c9f3acb444..0da26f956ae 100644 --- a/src/vs/editor/browser/viewParts/decorations/decorations.ts +++ b/src/vs/editor/browser/viewParts/decorations/decorations.ts @@ -64,7 +64,7 @@ export class DecorationsOverlay extends DynamicViewOverlay { } return true; } - public onLayoutChanged(layoutInfo:editorCommon.IEditorLayoutInfo): boolean { + public onLayoutChanged(layoutInfo:editorCommon.EditorLayoutInfo): boolean { return true; } public onScrollChanged(e:editorCommon.IScrollEvent): boolean { diff --git a/src/vs/editor/browser/viewParts/glyphMargin/glyphMargin.ts b/src/vs/editor/browser/viewParts/glyphMargin/glyphMargin.ts index 5ae7e66265c..ea5a5c9d323 100644 --- a/src/vs/editor/browser/viewParts/glyphMargin/glyphMargin.ts +++ b/src/vs/editor/browser/viewParts/glyphMargin/glyphMargin.ts @@ -135,7 +135,7 @@ export class GlyphMarginOverlay extends DedupOverlay { } return true; } - public onLayoutChanged(layoutInfo:editorCommon.IEditorLayoutInfo): boolean { + public onLayoutChanged(layoutInfo:editorCommon.EditorLayoutInfo): boolean { this._glyphMarginLeft = layoutInfo.glyphMarginLeft; this._glyphMarginWidth = layoutInfo.glyphMarginWidth; return true; diff --git a/src/vs/editor/browser/viewParts/lineNumbers/lineNumbers.ts b/src/vs/editor/browser/viewParts/lineNumbers/lineNumbers.ts index 373a417ccfe..50aaa13d5c9 100644 --- a/src/vs/editor/browser/viewParts/lineNumbers/lineNumbers.ts +++ b/src/vs/editor/browser/viewParts/lineNumbers/lineNumbers.ts @@ -74,7 +74,7 @@ export class LineNumbersOverlay extends DynamicViewOverlay { } return true; } - public onLayoutChanged(layoutInfo:editorCommon.IEditorLayoutInfo): boolean { + public onLayoutChanged(layoutInfo:editorCommon.EditorLayoutInfo): boolean { this._lineNumbersLeft = layoutInfo.lineNumbersLeft; this._lineNumbersWidth = layoutInfo.lineNumbersWidth; return true; diff --git a/src/vs/editor/browser/viewParts/lines/viewLines.ts b/src/vs/editor/browser/viewParts/lines/viewLines.ts index d0cc972c7aa..26f212f10c0 100644 --- a/src/vs/editor/browser/viewParts/lines/viewLines.ts +++ b/src/vs/editor/browser/viewParts/lines/viewLines.ts @@ -129,7 +129,7 @@ export class ViewLines extends ViewLayer { return shouldRender; } - public onLayoutChanged(layoutInfo:editorCommon.IEditorLayoutInfo): boolean { + public onLayoutChanged(layoutInfo:editorCommon.EditorLayoutInfo): boolean { var shouldRender = super.onLayoutChanged(layoutInfo); this._maxLineWidth = 0; return shouldRender; diff --git a/src/vs/editor/browser/viewParts/linesDecorations/linesDecorations.ts b/src/vs/editor/browser/viewParts/linesDecorations/linesDecorations.ts index 5f59ccec8b6..af7280003be 100644 --- a/src/vs/editor/browser/viewParts/linesDecorations/linesDecorations.ts +++ b/src/vs/editor/browser/viewParts/linesDecorations/linesDecorations.ts @@ -68,7 +68,7 @@ export class LinesDecorationsOverlay extends DedupOverlay { } return true; } - public onLayoutChanged(layoutInfo:editorCommon.IEditorLayoutInfo): boolean { + public onLayoutChanged(layoutInfo:editorCommon.EditorLayoutInfo): boolean { this._decorationsLeft = layoutInfo.decorationsLeft; this._decorationsWidth = layoutInfo.decorationsWidth; return true; diff --git a/src/vs/editor/browser/viewParts/overlayWidgets/overlayWidgets.ts b/src/vs/editor/browser/viewParts/overlayWidgets/overlayWidgets.ts index acab912c69e..61302e0fd7a 100644 --- a/src/vs/editor/browser/viewParts/overlayWidgets/overlayWidgets.ts +++ b/src/vs/editor/browser/viewParts/overlayWidgets/overlayWidgets.ts @@ -7,7 +7,7 @@ import 'vs/css!./overlayWidgets'; import {StyleMutator} from 'vs/base/browser/styleMutator'; -import {IEditorLayoutInfo} from 'vs/editor/common/editorCommon'; +import {EditorLayoutInfo} from 'vs/editor/common/editorCommon'; import {ClassNames, IOverlayWidget, OverlayWidgetPositionPreference} from 'vs/editor/browser/editorBrowser'; import {ViewPart} from 'vs/editor/browser/view/viewPart'; import {ViewContext} from 'vs/editor/common/view/viewContext'; @@ -52,7 +52,7 @@ export class ViewOverlayWidgets extends ViewPart { // ---- begin view event handlers - public onLayoutChanged(layoutInfo:IEditorLayoutInfo): boolean { + public onLayoutChanged(layoutInfo:EditorLayoutInfo): boolean { this._verticalScrollbarWidth = layoutInfo.verticalScrollbarWidth; this._horizontalScrollbarHeight = layoutInfo.horizontalScrollbarHeight; this._editorHeight = layoutInfo.height; diff --git a/src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler.ts b/src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler.ts index 6659ead4000..94e294216ed 100644 --- a/src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler.ts +++ b/src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler.ts @@ -100,7 +100,7 @@ export class DecorationsOverviewRuler extends ViewPart { return shouldRender; } - public onLayoutChanged(layoutInfo:editorCommon.IEditorLayoutInfo): boolean { + public onLayoutChanged(layoutInfo:editorCommon.EditorLayoutInfo): boolean { this._overviewRuler.setLayout(layoutInfo.overviewRuler, false); return true; } diff --git a/src/vs/editor/browser/viewParts/scrollDecoration/scrollDecoration.ts b/src/vs/editor/browser/viewParts/scrollDecoration/scrollDecoration.ts index 292ff62c281..f605f5ffeb8 100644 --- a/src/vs/editor/browser/viewParts/scrollDecoration/scrollDecoration.ts +++ b/src/vs/editor/browser/viewParts/scrollDecoration/scrollDecoration.ts @@ -8,7 +8,7 @@ import 'vs/css!./scrollDecoration'; import * as dom from 'vs/base/browser/dom'; import {StyleMutator} from 'vs/base/browser/styleMutator'; -import {IConfigurationChangedEvent, IEditorLayoutInfo, IScrollEvent} from 'vs/editor/common/editorCommon'; +import {IConfigurationChangedEvent, EditorLayoutInfo, IScrollEvent} from 'vs/editor/common/editorCommon'; import {ClassNames} from 'vs/editor/browser/editorBrowser'; import {ViewPart} from 'vs/editor/browser/view/viewPart'; import {ViewContext} from 'vs/editor/common/view/viewContext'; @@ -53,7 +53,7 @@ export class ScrollDecorationViewPart extends ViewPart { } return this._updateShouldShow(); } - public onLayoutChanged(layoutInfo: IEditorLayoutInfo): boolean { + public onLayoutChanged(layoutInfo: EditorLayoutInfo): boolean { if (this._width !== layoutInfo.width) { this._width = layoutInfo.width; return true; diff --git a/src/vs/editor/browser/viewParts/selections/selections.ts b/src/vs/editor/browser/viewParts/selections/selections.ts index 751381fd62f..4d864f7ed1b 100644 --- a/src/vs/editor/browser/viewParts/selections/selections.ts +++ b/src/vs/editor/browser/viewParts/selections/selections.ts @@ -136,7 +136,7 @@ export class SelectionsOverlay extends DynamicViewOverlay { } return true; } - public onLayoutChanged(layoutInfo:editorCommon.IEditorLayoutInfo): boolean { + public onLayoutChanged(layoutInfo:editorCommon.EditorLayoutInfo): boolean { return true; } public onScrollChanged(e:editorCommon.IScrollEvent): boolean { diff --git a/src/vs/editor/browser/viewParts/viewCursors/viewCursors.ts b/src/vs/editor/browser/viewParts/viewCursors/viewCursors.ts index d588d199ce8..fd9622f642d 100644 --- a/src/vs/editor/browser/viewParts/viewCursors/viewCursors.ts +++ b/src/vs/editor/browser/viewParts/viewCursors/viewCursors.ts @@ -163,7 +163,7 @@ export class ViewCursors extends ViewPart { } return true; } - public onLayoutChanged(layoutInfo: editorCommon.IEditorLayoutInfo): boolean { + public onLayoutChanged(layoutInfo: editorCommon.EditorLayoutInfo): boolean { return true; } public onScrollChanged(e: editorCommon.IScrollEvent): boolean { diff --git a/src/vs/editor/browser/viewParts/viewZones/viewZones.ts b/src/vs/editor/browser/viewParts/viewZones/viewZones.ts index 3a3718ac2b0..2e7cdd6515d 100644 --- a/src/vs/editor/browser/viewParts/viewZones/viewZones.ts +++ b/src/vs/editor/browser/viewParts/viewZones/viewZones.ts @@ -87,7 +87,7 @@ export class ViewZones extends ViewPart { return this._recomputeWhitespacesProps(); } - public onLayoutChanged(layoutInfo:editorCommon.IEditorLayoutInfo): boolean { + public onLayoutChanged(layoutInfo:editorCommon.EditorLayoutInfo): boolean { return true; } diff --git a/src/vs/editor/browser/widget/diffEditorWidget.ts b/src/vs/editor/browser/widget/diffEditorWidget.ts index 08de0c5863c..83bf01e5247 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget.ts @@ -1594,7 +1594,7 @@ class DiffEdtorWidgetInline extends DiffEditorWidgetStyle implements IDiffEditor this.decorationsLeft = dataSource.getOriginalEditor().getLayoutInfo().decorationsLeft; this.toDispose = []; - this.toDispose.push(dataSource.getOriginalEditor().addListener2(editorCommon.EventType.EditorLayout, (layoutInfo:editorCommon.IEditorLayoutInfo) => { + this.toDispose.push(dataSource.getOriginalEditor().addListener2(editorCommon.EventType.EditorLayout, (layoutInfo:editorCommon.EditorLayoutInfo) => { if (this.decorationsLeft !== layoutInfo.decorationsLeft) { this.decorationsLeft = layoutInfo.decorationsLeft; dataSource.relayoutEditors(); diff --git a/src/vs/editor/common/commonCodeEditor.ts b/src/vs/editor/common/commonCodeEditor.ts index 0b8f82df25d..abfd2b1b5ff 100644 --- a/src/vs/editor/common/commonCodeEditor.ts +++ b/src/vs/editor/common/commonCodeEditor.ts @@ -656,7 +656,7 @@ export abstract class CommonCodeEditor extends EventEmitter implements IActionPr }; } - public getLayoutInfo(): editorCommon.IEditorLayoutInfo { + public getLayoutInfo(): editorCommon.EditorLayoutInfo { return this._configuration.editor.layoutInfo; } diff --git a/src/vs/editor/common/config/commonEditorConfig.ts b/src/vs/editor/common/config/commonEditorConfig.ts index 28835b01079..95321852730 100644 --- a/src/vs/editor/common/config/commonEditorConfig.ts +++ b/src/vs/editor/common/config/commonEditorConfig.ts @@ -13,7 +13,7 @@ import {Extensions, IConfigurationRegistry, IConfigurationNode} from 'vs/platfor import {Registry} from 'vs/platform/platform'; import {DefaultConfig, DEFAULT_INDENTATION, GOLDEN_LINE_HEIGHT_RATIO} from 'vs/editor/common/config/defaultConfig'; import * as editorCommon from 'vs/editor/common/editorCommon'; -import {EditorLayoutProvider, EditorLayoutInfo} from 'vs/editor/common/viewLayout/editorLayoutProvider'; +import {EditorLayoutProvider} from 'vs/editor/common/viewLayout/editorLayoutProvider'; /** * Experimental screen reader support toggle @@ -109,7 +109,7 @@ export class InternalEditorOptions implements editorCommon.IInternalEditorOption indentGuides: boolean; useTabStops: boolean; trimAutoWhitespace: boolean; - layoutInfo: EditorLayoutInfo; + layoutInfo: editorCommon.EditorLayoutInfo; fontInfo: editorCommon.FontInfo; editorClassName: string; wrappingInfo: editorCommon.IEditorWrappingInfo; @@ -177,7 +177,7 @@ export class InternalEditorOptions implements editorCommon.IInternalEditorOption this.indentGuides = Boolean(input.indentGuides); this.useTabStops = Boolean(input.useTabStops); this.trimAutoWhitespace = Boolean(input.trimAutoWhitespace); - this.layoutInfo = new EditorLayoutInfo(input.layoutInfo); + this.layoutInfo = input.layoutInfo.clone(); this.fontInfo = input.fontInfo.clone(); this.editorClassName = input.editorClassName; this.wrappingInfo = { diff --git a/src/vs/editor/common/editorCommon.ts b/src/vs/editor/common/editorCommon.ts index d2113fcbdd0..0556264111f 100644 --- a/src/vs/editor/common/editorCommon.ts +++ b/src/vs/editor/common/editorCommon.ts @@ -637,7 +637,7 @@ export interface IInternalEditorOptions { // ---- Options that are computed - layoutInfo: IEditorLayoutInfo; + layoutInfo: EditorLayoutInfo; fontInfo: FontInfo; editorClassName: string; @@ -2155,7 +2155,9 @@ export class OverviewRulerPosition { /** * The internal layout details of the editor. */ -export interface IEditorLayoutInfo { +export class EditorLayoutInfo { + _editorLayoutInfoBrand: void; + /** * Full editor width. */ @@ -2230,6 +2232,70 @@ export interface IEditorLayoutInfo { * The position of the overview ruler. */ overviewRuler:OverviewRulerPosition; + + constructor(source:{ + width:number; + height:number; + glyphMarginLeft:number; + glyphMarginWidth:number; + glyphMarginHeight:number; + lineNumbersLeft:number; + lineNumbersWidth:number; + lineNumbersHeight:number; + decorationsLeft:number; + decorationsWidth:number; + decorationsHeight:number; + contentLeft:number; + contentWidth:number; + contentHeight:number; + verticalScrollbarWidth:number; + horizontalScrollbarHeight:number; + overviewRuler:OverviewRulerPosition; + }) { + this.width = source.width|0; + this.height = source.height|0; + this.glyphMarginLeft = source.glyphMarginLeft|0; + this.glyphMarginWidth = source.glyphMarginWidth|0; + this.glyphMarginHeight = source.glyphMarginHeight|0; + this.lineNumbersLeft = source.lineNumbersLeft|0; + this.lineNumbersWidth = source.lineNumbersWidth|0; + this.lineNumbersHeight = source.lineNumbersHeight|0; + this.decorationsLeft = source.decorationsLeft|0; + this.decorationsWidth = source.decorationsWidth|0; + this.decorationsHeight = source.decorationsHeight|0; + this.contentLeft = source.contentLeft|0; + this.contentWidth = source.contentWidth|0; + this.contentHeight = source.contentHeight|0; + this.verticalScrollbarWidth = source.verticalScrollbarWidth|0; + this.horizontalScrollbarHeight = source.horizontalScrollbarHeight|0; + this.overviewRuler = source.overviewRuler.clone(); + } + + public equals(other:EditorLayoutInfo): boolean { + return ( + this.width === other.width + && this.height === other.height + && this.glyphMarginLeft === other.glyphMarginLeft + && this.glyphMarginWidth === other.glyphMarginWidth + && this.glyphMarginHeight === other.glyphMarginHeight + && this.lineNumbersLeft === other.lineNumbersLeft + && this.lineNumbersWidth === other.lineNumbersWidth + && this.lineNumbersHeight === other.lineNumbersHeight + && this.decorationsLeft === other.decorationsLeft + && this.decorationsWidth === other.decorationsWidth + && this.decorationsHeight === other.decorationsHeight + && this.contentLeft === other.contentLeft + && this.contentWidth === other.contentWidth + && this.contentHeight === other.contentHeight + && this.verticalScrollbarWidth === other.verticalScrollbarWidth + && this.horizontalScrollbarHeight === other.horizontalScrollbarHeight + && this.overviewRuler.equals(other.overviewRuler) + ); + } + + public clone(): EditorLayoutInfo { + return new EditorLayoutInfo(this); + } } /** @@ -3114,7 +3180,7 @@ export interface ICommonCodeEditor extends IEditor { /** * Get the layout info for the editor. */ - getLayoutInfo(): IEditorLayoutInfo; + getLayoutInfo(): EditorLayoutInfo; /** * Prevent the editor from sending a widgetFocusLost event, diff --git a/src/vs/editor/common/viewLayout/editorLayoutProvider.ts b/src/vs/editor/common/viewLayout/editorLayoutProvider.ts index 8ae69ae9f84..347a002c848 100644 --- a/src/vs/editor/common/viewLayout/editorLayoutProvider.ts +++ b/src/vs/editor/common/viewLayout/editorLayoutProvider.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import {IEditorLayoutInfo, OverviewRulerPosition} from 'vs/editor/common/editorCommon'; +import {EditorLayoutInfo, OverviewRulerPosition} from 'vs/editor/common/editorCommon'; export interface IEditorLayoutProviderOpts { outerWidth:number; @@ -26,76 +26,7 @@ export interface IEditorLayoutProviderOpts { horizontalScrollbarHeight:number; } -export class EditorLayoutInfo implements IEditorLayoutInfo { - _editorLayoutInfoBrand: void; - - public width:number; - public height:number; - public glyphMarginLeft:number; - public glyphMarginWidth:number; - public glyphMarginHeight:number; - public lineNumbersLeft:number; - public lineNumbersWidth:number; - public lineNumbersHeight:number; - public decorationsLeft:number; - public decorationsWidth:number; - public decorationsHeight:number; - public contentLeft:number; - public contentWidth:number; - public contentHeight:number; - public verticalScrollbarWidth:number; - public horizontalScrollbarHeight:number; - public overviewRuler:OverviewRulerPosition; - - constructor(source:IEditorLayoutInfo) { - this.width = source.width|0; - this.height = source.height|0; - this.glyphMarginLeft = source.glyphMarginLeft|0; - this.glyphMarginWidth = source.glyphMarginWidth|0; - this.glyphMarginHeight = source.glyphMarginHeight|0; - this.lineNumbersLeft = source.lineNumbersLeft|0; - this.lineNumbersWidth = source.lineNumbersWidth|0; - this.lineNumbersHeight = source.lineNumbersHeight|0; - this.decorationsLeft = source.decorationsLeft|0; - this.decorationsWidth = source.decorationsWidth|0; - this.decorationsHeight = source.decorationsHeight|0; - this.contentLeft = source.contentLeft|0; - this.contentWidth = source.contentWidth|0; - this.contentHeight = source.contentHeight|0; - this.verticalScrollbarWidth = source.verticalScrollbarWidth|0; - this.horizontalScrollbarHeight = source.horizontalScrollbarHeight|0; - this.overviewRuler = source.overviewRuler.clone(); - } - - public equals(other:EditorLayoutInfo): boolean { - return ( - this.width === other.width - && this.height === other.height - && this.glyphMarginLeft === other.glyphMarginLeft - && this.glyphMarginWidth === other.glyphMarginWidth - && this.glyphMarginHeight === other.glyphMarginHeight - && this.lineNumbersLeft === other.lineNumbersLeft - && this.lineNumbersWidth === other.lineNumbersWidth - && this.lineNumbersHeight === other.lineNumbersHeight - && this.decorationsLeft === other.decorationsLeft - && this.decorationsWidth === other.decorationsWidth - && this.decorationsHeight === other.decorationsHeight - && this.contentLeft === other.contentLeft - && this.contentWidth === other.contentWidth - && this.contentHeight === other.contentHeight - && this.verticalScrollbarWidth === other.verticalScrollbarWidth - && this.horizontalScrollbarHeight === other.horizontalScrollbarHeight - && this.overviewRuler.equals(other.overviewRuler) - ); - } - - public clone(): EditorLayoutInfo { - return new EditorLayoutInfo(this); - } -} - export class EditorLayoutProvider { - public static compute(_opts:IEditorLayoutProviderOpts): EditorLayoutInfo { const outerWidth = _opts.outerWidth|0; const outerHeight = _opts.outerHeight|0; diff --git a/src/vs/editor/common/viewModel/viewEventHandler.ts b/src/vs/editor/common/viewModel/viewEventHandler.ts index da40e82551f..c5889d87f16 100644 --- a/src/vs/editor/common/viewModel/viewEventHandler.ts +++ b/src/vs/editor/common/viewModel/viewEventHandler.ts @@ -65,7 +65,7 @@ export class ViewEventHandler { public onConfigurationChanged(e:editorCommon.IConfigurationChangedEvent): boolean { return false; } - public onLayoutChanged(layoutInfo:editorCommon.IEditorLayoutInfo): boolean { + public onLayoutChanged(layoutInfo:editorCommon.EditorLayoutInfo): boolean { return false; } public onScrollChanged(e:editorCommon.IScrollEvent): boolean { @@ -163,7 +163,7 @@ export class ViewEventHandler { break; case editorCommon.EventType.ViewLayoutChanged: - if (this.onLayoutChanged(data)) { + if (this.onLayoutChanged(data)) { shouldRender = true; } break; diff --git a/src/vs/editor/contrib/zoneWidget/browser/zoneWidget.ts b/src/vs/editor/contrib/zoneWidget/browser/zoneWidget.ts index 554f1b96acc..458016f2417 100644 --- a/src/vs/editor/contrib/zoneWidget/browser/zoneWidget.ts +++ b/src/vs/editor/contrib/zoneWidget/browser/zoneWidget.ts @@ -10,7 +10,7 @@ import {Disposables} from 'vs/base/common/lifecycle'; import * as objects from 'vs/base/common/objects'; import * as dom from 'vs/base/browser/dom'; import {Sash, Orientation, IHorizontalSashLayoutProvider, ISashEvent} from 'vs/base/browser/ui/sash/sash'; -import {EventType, IEditorLayoutInfo, IPosition, IRange} from 'vs/editor/common/editorCommon'; +import {EventType, EditorLayoutInfo, IPosition, IRange} from 'vs/editor/common/editorCommon'; import {Range} from 'vs/editor/common/core/range'; import {Position} from 'vs/editor/common/core/position'; import {ICodeEditor, IOverlayWidget, IOverlayWidgetPosition, IViewZone, IViewZoneChangeAccessor} from 'vs/editor/browser/editorBrowser'; @@ -111,7 +111,7 @@ export abstract class ZoneWidget implements IHorizontalSashLayoutProvider { this.domNode.setAttribute('role', 'presentation'); } - this._disposables.add(this.editor.addListener2(EventType.EditorLayout, (info: IEditorLayoutInfo) => { + this._disposables.add(this.editor.addListener2(EventType.EditorLayout, (info: EditorLayoutInfo) => { var width = this._getWidth(info); this.domNode.style.width = width + 'px'; this._onWidth(width); @@ -131,7 +131,7 @@ export abstract class ZoneWidget implements IHorizontalSashLayoutProvider { this._initSash(); } - private _getWidth(info: IEditorLayoutInfo = this.editor.getLayoutInfo()): number { + private _getWidth(info: EditorLayoutInfo = this.editor.getLayoutInfo()): number { return info.width - info.verticalScrollbarWidth; } diff --git a/src/vs/editor/test/common/viewLayout/editorLayoutProvider.test.ts b/src/vs/editor/test/common/viewLayout/editorLayoutProvider.test.ts index d45f132e463..7e32f51e16a 100644 --- a/src/vs/editor/test/common/viewLayout/editorLayoutProvider.test.ts +++ b/src/vs/editor/test/common/viewLayout/editorLayoutProvider.test.ts @@ -5,12 +5,12 @@ 'use strict'; import * as assert from 'assert'; -import {IEditorLayoutInfo, OverviewRulerPosition} from 'vs/editor/common/editorCommon'; +import {EditorLayoutInfo, OverviewRulerPosition} from 'vs/editor/common/editorCommon'; import {EditorLayoutProvider, IEditorLayoutProviderOpts} from 'vs/editor/common/viewLayout/editorLayoutProvider'; suite('Editor ViewLayout - EditorLayoutProvider', () => { - function doTest(input:IEditorLayoutProviderOpts, expected:IEditorLayoutInfo): void { + function doTest(input:IEditorLayoutProviderOpts, expected:EditorLayoutInfo): void { let actual = EditorLayoutProvider.compute(input); assert.deepEqual(actual, expected); } @@ -30,7 +30,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { horizontalScrollbarHeight: 0, scrollbarArrowSize: 0, verticalScrollbarHasArrows: false - }, { + }, new EditorLayoutInfo({ width:1000, height:800, @@ -59,7 +59,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { height: 800, right: 0 }) - }); + })); }); test('EditorLayoutProvider 1.1', () => { @@ -77,7 +77,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { horizontalScrollbarHeight: 12, scrollbarArrowSize: 13, verticalScrollbarHasArrows: true - }, { + }, new EditorLayoutInfo({ width:1000, height:800, @@ -106,7 +106,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { height: (800 - 2 * 13), right: 0 }) - }); + })); }); test('EditorLayoutProvider 2', () => { @@ -124,7 +124,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { horizontalScrollbarHeight: 0, scrollbarArrowSize: 0, verticalScrollbarHasArrows: false - }, { + }, new EditorLayoutInfo({ width:900, height:800, @@ -153,7 +153,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { height: 800, right: 0 }) - }); + })); }); test('EditorLayoutProvider 3', () => { @@ -171,7 +171,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { horizontalScrollbarHeight: 0, scrollbarArrowSize: 0, verticalScrollbarHasArrows: false - }, { + }, new EditorLayoutInfo({ width:900, height:900, @@ -200,7 +200,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { height: 900, right: 0 }) - }); + })); }); test('EditorLayoutProvider 4', () => { @@ -218,7 +218,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { horizontalScrollbarHeight: 0, scrollbarArrowSize: 0, verticalScrollbarHasArrows: false - }, { + }, new EditorLayoutInfo({ width:900, height:900, @@ -247,7 +247,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { height: 900, right: 0 }) - }); + })); }); test('EditorLayoutProvider 5', () => { @@ -265,7 +265,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { horizontalScrollbarHeight: 0, scrollbarArrowSize: 0, verticalScrollbarHasArrows: false - }, { + }, new EditorLayoutInfo({ width:900, height:900, @@ -294,7 +294,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { height: 900, right: 0 }) - }); + })); }); test('EditorLayoutProvider 6', () => { @@ -312,7 +312,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { horizontalScrollbarHeight: 0, scrollbarArrowSize: 0, verticalScrollbarHasArrows: false - }, { + }, new EditorLayoutInfo({ width:900, height:900, @@ -341,7 +341,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { height: 900, right: 0 }) - }); + })); }); test('EditorLayoutProvider 7', () => { @@ -359,7 +359,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { horizontalScrollbarHeight: 0, scrollbarArrowSize: 0, verticalScrollbarHasArrows: false - }, { + }, new EditorLayoutInfo({ width:900, height:900, @@ -388,7 +388,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { height: 900, right: 0 }) - }); + })); }); test('EditorLayoutProvider 8', () => { @@ -406,7 +406,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { horizontalScrollbarHeight: 0, scrollbarArrowSize: 0, verticalScrollbarHasArrows: false - }, { + }, new EditorLayoutInfo({ width:900, height:900, @@ -435,7 +435,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { height: 900, right: 0 }) - }); + })); }); test('EditorLayoutProvider 8 - rounds floats', () => { @@ -453,7 +453,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { horizontalScrollbarHeight: 0, scrollbarArrowSize: 0, verticalScrollbarHasArrows: false - }, { + }, new EditorLayoutInfo({ width:900, height:900, @@ -482,6 +482,6 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { height: 900, right: 0 }) - }); + })); }); }); From 6d0aa3bc918162e05ed5f61dead03f890f499098 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 6 May 2016 12:21:30 +0200 Subject: [PATCH 080/297] spell out appRoot and extRoot instead of generic clean-up patterns --- .../telemetry/browser/telemetryService.ts | 19 +++++++++++++------ src/vs/workbench/electron-browser/shell.ts | 7 ++----- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/vs/platform/telemetry/browser/telemetryService.ts b/src/vs/platform/telemetry/browser/telemetryService.ts index d59020085e3..173e9fa08b6 100644 --- a/src/vs/platform/telemetry/browser/telemetryService.ts +++ b/src/vs/platform/telemetry/browser/telemetryService.ts @@ -7,6 +7,7 @@ import * as Platform from 'vs/base/common/platform'; import * as uuid from 'vs/base/common/uuid'; +import {escapeRegExpCharacters} from 'vs/base/common/strings'; import {ITelemetryService, ITelemetryAppender, ITelemetryInfo} from 'vs/platform/telemetry/common/telemetry'; import ErrorTelemetry from 'vs/platform/telemetry/common/errorTelemetry'; import {IdleMonitor, UserStatus} from 'vs/base/browser/idleMonitor'; @@ -17,14 +18,13 @@ import {withDefaults, cloneAndChange} from 'vs/base/common/objects'; export interface ITelemetryServiceConfig { userOptIn?: boolean; - enableHardIdle?: boolean; enableSoftIdle?: boolean; sessionID?: string; commitHash?: string; version?: string; - - cleanupPatterns?: [RegExp,string][]; + appRoot?: string; + extensionsRoot?: string; } export class TelemetryService implements ITelemetryService { @@ -50,6 +50,7 @@ export class TelemetryService implements ITelemetryService { private _startTime = new Date(); private _optInFriendly = ['optInStatus']; //holds a cache of predefined events that can be sent regardress of user optin status private _userIdHash: string; + private _cleanupPatterns: [RegExp, string][]= []; constructor(config?: ITelemetryServiceConfig) { this._configuration = withDefaults(config, { @@ -57,14 +58,20 @@ export class TelemetryService implements ITelemetryService { sessionID: uuid.generateUuid() + Date.now(), enableHardIdle: true, enableSoftIdle: true, - userOptIn: true, + userOptIn: true }); // static cleanup patterns for: // #1 `file:///DANGEROUS/PATH/resources/app/Useful/Information` // #2 // Any other file path that doesn't match the approved form above should be cleaned. // #3 "Error: ENOENT; no such file or directory" is often followed with PII, clean it - this._configuration.cleanupPatterns.push( + if (this._configuration.appRoot) { + this._cleanupPatterns.push([new RegExp(escapeRegExpCharacters(this._configuration.appRoot), 'gi'), '']); + } + if (this._configuration.extensionsRoot) { + this._cleanupPatterns.push([new RegExp(escapeRegExpCharacters(this._configuration.extensionsRoot), 'gi'), '']); + } + this._cleanupPatterns.push( [/file:\/\/\/.*?\/resources\/app\//gi, ''], [/file:\/\/\/.*/gi, ''], [/ENOENT: no such file or directory.*?\'([^\']+)\'/gi, 'ENOENT: no such file or directory'] @@ -186,7 +193,7 @@ export class TelemetryService implements ITelemetryService { private _cleanupInfo(stack: string): string { // sanitize with configured cleanup patterns - for (let tuple of this._configuration.cleanupPatterns) { + for (let tuple of this._cleanupPatterns) { let [regexp, replaceValue] = tuple; stack = stack.replace(regexp, replaceValue); } diff --git a/src/vs/workbench/electron-browser/shell.ts b/src/vs/workbench/electron-browser/shell.ts index 2f6a2bc0e0b..c8e755ef96f 100644 --- a/src/vs/workbench/electron-browser/shell.ts +++ b/src/vs/workbench/electron-browser/shell.ts @@ -11,7 +11,6 @@ import * as nls from 'vs/nls'; import {TPromise} from 'vs/base/common/winjs.base'; import * as platform from 'vs/base/common/platform'; import {Dimension, Builder, $} from 'vs/base/browser/builder'; -import {escapeRegExpCharacters} from 'vs/base/common/strings'; import dom = require('vs/base/browser/dom'); import aria = require('vs/base/browser/ui/aria/aria'); import {dispose, IDisposable} from 'vs/base/common/lifecycle'; @@ -205,10 +204,8 @@ export class WorkbenchShell { if (this.configuration.env.isBuilt && !this.configuration.env.extensionDevelopmentPath && !!this.configuration.env.enableTelemetry) { this.telemetryService = new ElectronTelemetryService(this.configurationService, this.storageService, { - cleanupPatterns: [ - [new RegExp(escapeRegExpCharacters(this.configuration.env.appRoot), 'gi'), ''], - [new RegExp(escapeRegExpCharacters(this.configuration.env.userExtensionsHome), 'gi'), ''] - ], + appRoot: this.configuration.env.appRoot, + extensionsRoot: this.configuration.env.userExtensionsHome, version: this.configuration.env.version, commitHash: this.configuration.env.commitHash }); From d99d89dc711b0fd3e02e3d70b5c4516efdf36251 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 6 May 2016 12:53:28 +0200 Subject: [PATCH 081/297] make appenders a ctor argument, first step towards oop appender, #1000 --- .../telemetry/browser/telemetryService.ts | 19 +- src/vs/platform/telemetry/common/telemetry.ts | 30 +--- .../telemetry/node/appInsightsAppender.ts} | 22 +-- .../test/node/appInsightsAppender.test.ts} | 20 +-- .../test/node/telemetryService.test.ts | 162 +++--------------- src/vs/workbench/browser/workbench.ts | 4 +- src/vs/workbench/electron-browser/shell.ts | 4 +- .../appInsights.telemetry.contribution.ts | 11 -- src/vs/workbench/workbench.main.js | 2 - 9 files changed, 53 insertions(+), 221 deletions(-) rename src/vs/{workbench/parts/telemetry/node/nodeAppInsightsTelemetryAppender.ts => platform/telemetry/node/appInsightsAppender.ts} (88%) rename src/vs/{workbench/parts/telemetry/test/node/appInsightsTelemetryAppender.test.ts => platform/telemetry/test/node/appInsightsAppender.test.ts} (66%) delete mode 100644 src/vs/workbench/parts/telemetry/node/appInsights.telemetry.contribution.ts diff --git a/src/vs/platform/telemetry/browser/telemetryService.ts b/src/vs/platform/telemetry/browser/telemetryService.ts index 173e9fa08b6..1399a730080 100644 --- a/src/vs/platform/telemetry/browser/telemetryService.ts +++ b/src/vs/platform/telemetry/browser/telemetryService.ts @@ -17,6 +17,7 @@ import {TimeKeeper, ITimerEvent} from 'vs/base/common/timer'; import {withDefaults, cloneAndChange} from 'vs/base/common/objects'; export interface ITelemetryServiceConfig { + appender: ITelemetryAppender[]; userOptIn?: boolean; enableHardIdle?: boolean; enableSoftIdle?: boolean; @@ -40,7 +41,6 @@ export class TelemetryService implements ITelemetryService { protected _telemetryInfo: ITelemetryInfo; protected _configuration: ITelemetryServiceConfig; - protected _appenders: ITelemetryAppender[] = []; protected _disposables: IDisposable[] = []; private _timeKeeper: TimeKeeper; @@ -54,6 +54,7 @@ export class TelemetryService implements ITelemetryService { constructor(config?: ITelemetryServiceConfig) { this._configuration = withDefaults(config, { + appender: [], cleanupPatterns: [], sessionID: uuid.generateUuid() + Date.now(), enableHardIdle: true, @@ -131,7 +132,7 @@ export class TelemetryService implements ITelemetryService { public dispose(): void { this._disposables = dispose(this._disposables); - for (let appender of this._appenders) { + for (let appender of this._configuration.appender) { appender.dispose(); } } @@ -185,7 +186,7 @@ export class TelemetryService implements ITelemetryService { } }); - for (let appender of this._appenders) { + for (let appender of this._configuration.appender) { appender.log(eventName, data); } } @@ -200,17 +201,5 @@ export class TelemetryService implements ITelemetryService { return stack; } - - public addTelemetryAppender(appender: ITelemetryAppender): IDisposable { - this._appenders.push(appender); - return { - dispose: () => { - let index = this._appenders.indexOf(appender); - if (index > -1) { - this._appenders.splice(index, 1); - } - } - }; - } } diff --git a/src/vs/platform/telemetry/common/telemetry.ts b/src/vs/platform/telemetry/common/telemetry.ts index 6131d8b9646..5c8ea8ef9bf 100644 --- a/src/vs/platform/telemetry/common/telemetry.ts +++ b/src/vs/platform/telemetry/common/telemetry.ts @@ -7,7 +7,7 @@ import {TPromise} from 'vs/base/common/winjs.base'; import {IDisposable} from 'vs/base/common/lifecycle'; import {ITimerEvent, nullEvent} from 'vs/base/common/timer'; -import {createDecorator, ServiceIdentifier, IInstantiationService, ServicesAccessor, IConstructorSignature0} from 'vs/platform/instantiation/common/instantiation'; +import {createDecorator, ServiceIdentifier} from 'vs/platform/instantiation/common/instantiation'; export const ITelemetryService = createDecorator('telemetryService'); @@ -34,40 +34,12 @@ export interface ITelemetryService { getTelemetryInfo(): TPromise; isOptedIn: boolean; - - addTelemetryAppender(appender: ITelemetryAppender): IDisposable; -} - -export namespace Extenstions { - - let _telemetryAppenderCtors: IConstructorSignature0[] = []; - - export const TelemetryAppenders = { - activate(accessor: ServicesAccessor): void { - const telemetryService = accessor.get(ITelemetryService); - const instantiationService = accessor.get(IInstantiationService); - for (let ctor of _telemetryAppenderCtors) { - const instance = instantiationService.createInstance(ctor); - telemetryService.addTelemetryAppender(instance); - } - // can only be done once - _telemetryAppenderCtors = undefined; - }, - registerTelemetryAppenderDescriptor(ctor: IConstructorSignature0): void { - _telemetryAppenderCtors.push(ctor); - } - }; -}; - -export interface ITelemetryAppendersRegistry { - activate(instantiationService: IInstantiationService): void; } export const NullTelemetryService: ITelemetryService = { serviceId: undefined, timedPublicLog(name: string, data?: any): ITimerEvent { return nullEvent; }, publicLog(eventName: string, data?: any): void { }, - addTelemetryAppender(appender): IDisposable { return { dispose() { } }; }, isOptedIn: true, getTelemetryInfo(): TPromise { return TPromise.as({ diff --git a/src/vs/workbench/parts/telemetry/node/nodeAppInsightsTelemetryAppender.ts b/src/vs/platform/telemetry/node/appInsightsAppender.ts similarity index 88% rename from src/vs/workbench/parts/telemetry/node/nodeAppInsightsTelemetryAppender.ts rename to src/vs/platform/telemetry/node/appInsightsAppender.ts index cfff1bc911c..2a71bc85193 100644 --- a/src/vs/workbench/parts/telemetry/node/nodeAppInsightsTelemetryAppender.ts +++ b/src/vs/platform/telemetry/node/appInsightsAppender.ts @@ -4,14 +4,11 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -/* tslint:disable:semicolon */ - import errors = require('vs/base/common/errors'); import {IStorageService} from 'vs/platform/storage/common/storage'; import {ITelemetryAppender} from 'vs/platform/telemetry/common/telemetry'; import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace'; import {AIAdapter, IAIAdapter} from 'vs/base/node/aiAdapter'; - import winreg = require('winreg'); import os = require('os'); @@ -22,7 +19,7 @@ class StorageKeys { public static firstSessionDate: string = 'telemetry.firstSessionDate'; } -export class NodeAppInsightsTelemetryAppender implements ITelemetryAppender { +export class AppInsightsAppender implements ITelemetryAppender { public static EVENT_NAME_PREFIX: string = 'monacoworkbench'; @@ -40,8 +37,7 @@ export class NodeAppInsightsTelemetryAppender implements ITelemetryAppender { constructor( @IStorageService storageService: IStorageService, @IWorkspaceContextService contextService: IWorkspaceContextService, - /* for test only */ - client: any + _testing_client?: any ) { this.commonProperties = {}; this.commonMetrics = {}; @@ -54,21 +50,21 @@ export class NodeAppInsightsTelemetryAppender implements ITelemetryAppender { let asimovKey = config ? config.asimovKey: null; // for test - if (client) { - this.appInsights = client; + if (_testing_client) { + this.appInsights = _testing_client; if (asimovKey) { - this.appInsightsVortex = client; + this.appInsightsVortex = _testing_client; } return; } if (key) { - this.appInsights = new AIAdapter(key, NodeAppInsightsTelemetryAppender.EVENT_NAME_PREFIX); + this.appInsights = new AIAdapter(key, AppInsightsAppender.EVENT_NAME_PREFIX); } if(asimovKey) { - this.appInsightsVortex = new AIAdapter(asimovKey, NodeAppInsightsTelemetryAppender.EVENT_NAME_PREFIX); + this.appInsightsVortex = new AIAdapter(asimovKey, AppInsightsAppender.EVENT_NAME_PREFIX); } this.loadAddtionaProperties(); @@ -87,7 +83,7 @@ export class NodeAppInsightsTelemetryAppender implements ITelemetryAppender { if (sqmUserId) { this.commonProperties['sqm.userid'] = sqmUserId; } else { - this.getWinRegKeyData(NodeAppInsightsTelemetryAppender.SQM_KEY, 'UserId', winreg.HKCU, (error, result: string) => { + this.getWinRegKeyData(AppInsightsAppender.SQM_KEY, 'UserId', winreg.HKCU, (error, result: string) => { if (!error && result) { this.commonProperties['sqm.userid'] = result; this.storageService.store(StorageKeys.sqmUserId, result); @@ -100,7 +96,7 @@ export class NodeAppInsightsTelemetryAppender implements ITelemetryAppender { this.commonProperties['sqm.machineid'] = sqmMachineId; } else { - this.getWinRegKeyData(NodeAppInsightsTelemetryAppender.SQM_KEY, 'MachineId', winreg.HKLM,(error, result) => { + this.getWinRegKeyData(AppInsightsAppender.SQM_KEY, 'MachineId', winreg.HKLM,(error, result) => { if (!error && result) { this.commonProperties['sqm.machineid'] = result; this.storageService.store(StorageKeys.sqmMachineId, result); diff --git a/src/vs/workbench/parts/telemetry/test/node/appInsightsTelemetryAppender.test.ts b/src/vs/platform/telemetry/test/node/appInsightsAppender.test.ts similarity index 66% rename from src/vs/workbench/parts/telemetry/test/node/appInsightsTelemetryAppender.test.ts rename to src/vs/platform/telemetry/test/node/appInsightsAppender.test.ts index ae3246e2b8f..a69f4ebe8d5 100644 --- a/src/vs/workbench/parts/telemetry/test/node/appInsightsTelemetryAppender.test.ts +++ b/src/vs/platform/telemetry/test/node/appInsightsAppender.test.ts @@ -6,7 +6,7 @@ import * as assert from 'assert'; import {IAIAdapter} from 'vs/base/node/aiAdapter'; -import { NodeAppInsightsTelemetryAppender } from 'vs/workbench/parts/telemetry/node/nodeAppInsightsTelemetryAppender'; +import {AppInsightsAppender} from 'vs/platform/telemetry/node/appInsightsAppender'; interface IAppInsightsEvent { eventName: string; @@ -49,17 +49,17 @@ class ContextServiceMock { asimovKey: this.asimovKey } } - } + }; } } suite('Telemetry - AppInsightsTelemetryAppender', () => { var appInsightsMock: AIAdapterMock; - var appender: NodeAppInsightsTelemetryAppender; + var appender: AppInsightsAppender; setup(() => { - appInsightsMock = new AIAdapterMock(NodeAppInsightsTelemetryAppender.EVENT_NAME_PREFIX, NodeAppInsightsTelemetryAppender.EVENT_NAME_PREFIX); - appender = new NodeAppInsightsTelemetryAppender(null, new ContextServiceMock('123'), appInsightsMock); + appInsightsMock = new AIAdapterMock(AppInsightsAppender.EVENT_NAME_PREFIX, AppInsightsAppender.EVENT_NAME_PREFIX); + appender = new AppInsightsAppender(null, new ContextServiceMock('123'), appInsightsMock); }); teardown(() => { @@ -70,7 +70,7 @@ suite('Telemetry - AppInsightsTelemetryAppender', () => { appender.log('testEvent'); assert.equal(appInsightsMock.events.length, 1); - assert.equal(appInsightsMock.events[0].eventName, NodeAppInsightsTelemetryAppender.EVENT_NAME_PREFIX+'/testEvent'); + assert.equal(appInsightsMock.events[0].eventName, AppInsightsAppender.EVENT_NAME_PREFIX+'/testEvent'); }); test('Event with data', () => { @@ -81,7 +81,7 @@ suite('Telemetry - AppInsightsTelemetryAppender', () => { }); assert.equal(appInsightsMock.events.length, 1); - assert.equal(appInsightsMock.events[0].eventName, NodeAppInsightsTelemetryAppender.EVENT_NAME_PREFIX+'/testEvent'); + assert.equal(appInsightsMock.events[0].eventName, AppInsightsAppender.EVENT_NAME_PREFIX+'/testEvent'); assert.equal(appInsightsMock.events[0].data['title'], 'some title'); assert.equal(appInsightsMock.events[0].data['width'], 100); @@ -90,14 +90,14 @@ suite('Telemetry - AppInsightsTelemetryAppender', () => { }); test('Test asimov', () => { - appender = new NodeAppInsightsTelemetryAppender(null, new ContextServiceMock('123', 'AIF-123'), appInsightsMock); + appender = new AppInsightsAppender(null, new ContextServiceMock('123', 'AIF-123'), appInsightsMock); appender.log('testEvent'); assert.equal(appInsightsMock.events.length, 2); - assert.equal(appInsightsMock.events[0].eventName, NodeAppInsightsTelemetryAppender.EVENT_NAME_PREFIX+'/testEvent'); + assert.equal(appInsightsMock.events[0].eventName, AppInsightsAppender.EVENT_NAME_PREFIX+'/testEvent'); // test vortex - assert.equal(appInsightsMock.events[1].eventName, NodeAppInsightsTelemetryAppender.EVENT_NAME_PREFIX+'/testEvent'); + assert.equal(appInsightsMock.events[1].eventName, AppInsightsAppender.EVENT_NAME_PREFIX+'/testEvent'); }); }); \ No newline at end of file diff --git a/src/vs/platform/telemetry/test/node/telemetryService.test.ts b/src/vs/platform/telemetry/test/node/telemetryService.test.ts index fffe2d7307a..75401ac7183 100644 --- a/src/vs/platform/telemetry/test/node/telemetryService.test.ts +++ b/src/vs/platform/telemetry/test/node/telemetryService.test.ts @@ -8,8 +8,6 @@ import * as assert from 'assert'; import IdleMonitor = require('vs/base/browser/idleMonitor'); import {TelemetryService} from 'vs/platform/telemetry/browser/telemetryService'; import Telemetry = require('vs/platform/telemetry/common/telemetry'); -import {InstantiationService} from 'vs/platform/instantiation/common/instantiationService'; -import {ServiceCollection} from 'vs/platform/instantiation/common/serviceCollection'; import Errors = require('vs/base/common/errors'); import Timer = require('vs/base/common/timer'); import * as sinon from 'sinon'; @@ -88,7 +86,7 @@ suite('TelemetryService', () => { class AppenderCountTelemetryService extends TelemetryService { getAppendersCount() { - return this._appenders.length; + return this._configuration.appender.length; } } @@ -106,99 +104,9 @@ suite('TelemetryService', () => { service.dispose(); })); - test('Add appender', sinon.test(function() { - let service = new AppenderCountTelemetryService(); - assert.equal(service.getAppendersCount(), 0); - - let testAppender = new TestTelemetryAppender(); - service.addTelemetryAppender(testAppender); - - assert.equal(service.getAppendersCount(), 1); - service.dispose(); - })); - - test('Remove appender', sinon.test(function() { - let service = new AppenderCountTelemetryService(); - assert.equal(service.getAppendersCount(), 0); - - let testAppender = new TestTelemetryAppender(); - let registration = service.addTelemetryAppender(testAppender); - assert.equal(service.getAppendersCount(), 1); - - //report event - service.publicLog('testEvent'); - assert.equal(testAppender.getEventsCount(), 1); - - //remove appender - registration.dispose(); - assert.equal(service.getAppendersCount(), 0); - - //verify events not being sent - service.publicLog('testEvent2'); - assert.equal(testAppender.getEventsCount(), 1); - - service.dispose(); - })); - - test('Multiple appenders', sinon.test(function() { - let service = new AppenderCountTelemetryService(); - assert.equal(service.getAppendersCount(), 0); - - let testAppender1 = new TestTelemetryAppender(); - let registrgation1 = service.addTelemetryAppender(testAppender1); - assert.equal(service.getAppendersCount(), 1); - - //report event - service.publicLog('testEvent'); - assert.equal(testAppender1.getEventsCount(), 1); - - // add second appender - let testAppender2 = new TestTelemetryAppender(); - service.addTelemetryAppender(testAppender2); - assert.equal(service.getAppendersCount(), 2); - - //report event - service.publicLog('testEvent2'); - assert.equal(testAppender1.getEventsCount(), 2); - assert.equal(testAppender2.getEventsCount(), 1); - - //remove appender 1 - registrgation1.dispose(); - assert.equal(service.getAppendersCount(), 1); - - //verify events not being sent to the removed appender - service.publicLog('testEvent3'); - assert.equal(testAppender1.getEventsCount(), 2); - assert.equal(testAppender2.getEventsCount(), 2); - - service.dispose(); - })); - - test('TelemetryAppendersRegistry, activate', function() { - - Telemetry.Extenstions.TelemetryAppenders.registerTelemetryAppenderDescriptor(TestTelemetryAppender); - - let callCount = 0; - let telemetryService: Telemetry.ITelemetryService = { - addTelemetryAppender(appender) { - assert.ok(appender); - callCount += 1; - } - }; - - let instantiationService = new InstantiationService(new ServiceCollection([Telemetry.ITelemetryService, telemetryService])); - instantiationService.invokeFunction(Telemetry.Extenstions.TelemetryAppenders.activate); - assert.equal(callCount, 1); - - // registry is now active/read-only - assert.throws(() => Telemetry.Extenstions.TelemetryAppenders.registerTelemetryAppenderDescriptor(TestTelemetryAppender)); - assert.throws(() => instantiationService.invokeFunction(Telemetry.Extenstions.TelemetryAppenders.activate)); - }); - test('Disposing', sinon.test(function() { - let service = new TelemetryService(); let testAppender = new TestTelemetryAppender(); - service.addTelemetryAppender(testAppender); + let service = new TelemetryService({ appender: [testAppender] }); service.publicLog('testPrivateEvent'); assert.equal(testAppender.getEventsCount(), 1); @@ -209,12 +117,11 @@ suite('TelemetryService', () => { // event reporting test('Simple event', sinon.test(function() { - let service = new TelemetryService(); let testAppender = new TestTelemetryAppender(); + let service = new TelemetryService({ appender: [testAppender] }); return service.getTelemetryInfo().then(info => { - service.addTelemetryAppender(testAppender); service.publicLog('testEvent'); assert.equal(testAppender.getEventsCount(), 1); @@ -228,11 +135,10 @@ suite('TelemetryService', () => { })); test('Event with data', sinon.test(function() { - let service = new TelemetryService(); let testAppender = new TestTelemetryAppender(); + let service = new TelemetryService({ appender: [testAppender] }); return service.getTelemetryInfo().then(info => { - service.addTelemetryAppender(testAppender); service.publicLog('testEvent', { 'stringProp': 'property', @@ -260,9 +166,8 @@ suite('TelemetryService', () => { test('Telemetry Timer events', sinon.test(function() { Timer.ENABLE_TIMER = true; - let service = new TelemetryService(); let testAppender = new TestTelemetryAppender(); - service.addTelemetryAppender(testAppender); + let service = new TelemetryService({ appender: [testAppender] }); let t1 = service.timedPublicLog('editorDance'); this.clock.tick(20); @@ -293,9 +198,8 @@ suite('TelemetryService', () => { })); test('enableTelemetry on by default', sinon.test(function() { - let service = new TelemetryService(); let testAppender = new TestTelemetryAppender(); - service.addTelemetryAppender(testAppender); + let service = new TelemetryService({ appender: [testAppender] }); service.publicLog('testEvent'); assert.equal(testAppender.getEventsCount(), 1); @@ -310,9 +214,8 @@ suite('TelemetryService', () => { Errors.setUnexpectedErrorHandler(() => { }); try { - let service = new TelemetryService(); let testAppender = new TestTelemetryAppender(); - service.addTelemetryAppender(testAppender); + let service = new TelemetryService({ appender: [testAppender] }); let e: any = new Error('This is a test.'); @@ -365,9 +268,8 @@ suite('TelemetryService', () => { test('Handle global errors', sinon.test(function() { let errorStub = this.stub(window, 'onerror'); - let service = new TelemetryService(); let testAppender = new TestTelemetryAppender(); - service.addTelemetryAppender(testAppender); + let service = new TelemetryService({ appender: [testAppender] }); let testError = new Error('test'); (window.onerror)('Error Message', 'file.js', 2, 42, testError); @@ -390,9 +292,8 @@ suite('TelemetryService', () => { test('Uncaught Error Telemetry removes PII from filename', sinon.test(function() { let errorStub = this.stub(window, 'onerror'); let settings = new ErrorTestingSettings(); - let service = new TelemetryService(); let testAppender = new TestTelemetryAppender(); - service.addTelemetryAppender(testAppender); + let service = new TelemetryService({ appender: [testAppender] }); let dangerousFilenameError: any = new Error('dangerousFilename'); dangerousFilenameError.stack = settings.stack; @@ -419,9 +320,8 @@ suite('TelemetryService', () => { Errors.setUnexpectedErrorHandler(() => { }); try { let settings = new ErrorTestingSettings(); - let service = new TelemetryService(); let testAppender = new TestTelemetryAppender(); - service.addTelemetryAppender(testAppender); + let service = new TelemetryService({ appender: [testAppender] }); let dangerousPathWithoutImportantInfoError: any = new Error(settings.dangerousPathWithoutImportantInfo); dangerousPathWithoutImportantInfoError.stack = settings.stack; @@ -446,9 +346,8 @@ suite('TelemetryService', () => { test('Uncaught Error Telemetry removes PII', sinon.test(function() { let errorStub = this.stub(window, 'onerror'); let settings = new ErrorTestingSettings(); - let service = new TelemetryService(); let testAppender = new TestTelemetryAppender(); - service.addTelemetryAppender(testAppender); + let service = new TelemetryService({ appender: [testAppender] }); let dangerousPathWithoutImportantInfoError: any = new Error('dangerousPathWithoutImportantInfo'); dangerousPathWithoutImportantInfoError.stack = settings.stack; @@ -474,9 +373,8 @@ suite('TelemetryService', () => { try { let settings = new ErrorTestingSettings(); - let service = new TelemetryService(); let testAppender = new TestTelemetryAppender(); - service.addTelemetryAppender(testAppender); + let service = new TelemetryService({ appender: [testAppender] }); let dangerousPathWithImportantInfoError: any = new Error(settings.dangerousPathWithImportantInfo); dangerousPathWithImportantInfoError.stack = settings.stack; @@ -504,9 +402,8 @@ suite('TelemetryService', () => { test('Uncaught Error Telemetry removes PII but preserves Code file path', sinon.test(function() { let errorStub = this.stub(window, 'onerror'); let settings = new ErrorTestingSettings(); - let service = new TelemetryService(); let testAppender = new TestTelemetryAppender(); - service.addTelemetryAppender(testAppender); + let service = new TelemetryService({ appender: [testAppender] }); let dangerousPathWithImportantInfoError: any = new Error('dangerousPathWithImportantInfo'); dangerousPathWithImportantInfoError.stack = settings.stack; @@ -534,9 +431,8 @@ suite('TelemetryService', () => { try { let settings = new ErrorTestingSettings(); - let service = new TelemetryService(); let testAppender = new TestTelemetryAppender(); - service.addTelemetryAppender(testAppender); + let service = new TelemetryService({ appender: [testAppender] }); let missingModelError: any = new Error(settings.missingModelMessage); missingModelError.stack = settings.stack; @@ -564,9 +460,8 @@ suite('TelemetryService', () => { test('Uncaught Error Telemetry removes PII but preserves Missing Model error message', sinon.test(function() { let errorStub = this.stub(window, 'onerror'); let settings = new ErrorTestingSettings(); - let service = new TelemetryService(); let testAppender = new TestTelemetryAppender(); - service.addTelemetryAppender(testAppender); + let service = new TelemetryService({ appender: [testAppender] }); let missingModelError: any = new Error('missingModelMessage'); missingModelError.stack = settings.stack; @@ -595,9 +490,8 @@ suite('TelemetryService', () => { try { let settings = new ErrorTestingSettings(); - let service = new TelemetryService(); let testAppender = new TestTelemetryAppender(); - service.addTelemetryAppender(testAppender); + let service = new TelemetryService({ appender: [testAppender] }); let noSuchFileError: any = new Error(settings.noSuchFileMessage); noSuchFileError.stack = settings.stack; @@ -629,9 +523,8 @@ suite('TelemetryService', () => { try { let errorStub = this.stub(window, 'onerror'); let settings = new ErrorTestingSettings(); - let service = new TelemetryService(); let testAppender = new TestTelemetryAppender(); - service.addTelemetryAppender(testAppender); + let service = new TelemetryService({ appender: [testAppender] }); let noSuchFileError: any = new Error('noSuchFileMessage'); noSuchFileError.stack = settings.stack; @@ -659,9 +552,9 @@ suite('TelemetryService', () => { test('Test hard idle does not affect sending normal events in active state', sinon.test(function() { - let service = new TelemetryService({ enableHardIdle: true, enableSoftIdle: false }); let testAppender = new TestTelemetryAppender(); - service.addTelemetryAppender(testAppender); + let service = new TelemetryService({ enableHardIdle: true, enableSoftIdle: false, appender: [testAppender] }); + //report an event service.publicLog('testEvent'); @@ -675,9 +568,8 @@ suite('TelemetryService', () => { test('Test hard idle stops events from being sent in idle state', sinon.test(function() { - let service = new TelemetryService({ enableHardIdle: true, enableSoftIdle: false }); let testAppender = new TestTelemetryAppender(); - service.addTelemetryAppender(testAppender); + let service = new TelemetryService({ enableHardIdle: true, enableSoftIdle: false, appender: [testAppender] }); // make the user idle this.clock.tick(IdleMonitor.DEFAULT_IDLE_TIME); @@ -714,9 +606,8 @@ suite('TelemetryService', () => { this.stub(IdleMonitor, 'IdleMonitor', MockIdleMonitor); - let service = new TelemetryService({ enableHardIdle: false, enableSoftIdle: true }); let testAppender = new TestTelemetryAppender(); - service.addTelemetryAppender(testAppender); + let service = new TelemetryService({ enableHardIdle: false, enableSoftIdle: true, appender: [testAppender] }); assert.equal(testAppender.getEventsCount(), 0); @@ -741,7 +632,7 @@ suite('TelemetryService', () => { test('Telemetry Service uses provided session ID', sinon.test(function() { let testSessionId = 'test session id'; - let service = new TelemetryService({ sessionID: testSessionId }); + let service = new TelemetryService({ sessionID: testSessionId, appender: [] }); return service.getTelemetryInfo().then(info => { assert.equal(info.sessionId, testSessionId); @@ -750,9 +641,8 @@ suite('TelemetryService', () => { })); test('Telemetry Service respects user opt-in settings', sinon.test(function() { - let service = new TelemetryService({userOptIn: false }); let testAppender = new TestTelemetryAppender(); - service.addTelemetryAppender(testAppender); + let service = new TelemetryService({userOptIn: false, appender: [testAppender] }); service.publicLog('testEvent'); assert.equal(testAppender.getEventsCount(), 0); @@ -761,9 +651,8 @@ suite('TelemetryService', () => { })); test('Telemetry Service sends events when enableTelemetry is on even user optin is on', sinon.test(function() { - let service = new TelemetryService({userOptIn: true }); let testAppender = new TestTelemetryAppender(); - service.addTelemetryAppender(testAppender); + let service = new TelemetryService({userOptIn: true, appender: [testAppender] }); service.publicLog('testEvent'); assert.equal(testAppender.getEventsCount(), 1); @@ -772,9 +661,8 @@ suite('TelemetryService', () => { })); test('Telemetry Service allows optin friendly events', sinon.test(function() { - let service = new TelemetryService({userOptIn: false }); let testAppender = new TestTelemetryAppender(); - service.addTelemetryAppender(testAppender); + let service = new TelemetryService({userOptIn: false, appender: [testAppender] }); service.publicLog('testEvent'); assert.equal(testAppender.getEventsCount(), 0); diff --git a/src/vs/workbench/browser/workbench.ts b/src/vs/workbench/browser/workbench.ts index 116e84da39d..a1301c08d84 100644 --- a/src/vs/workbench/browser/workbench.ts +++ b/src/vs/workbench/browser/workbench.ts @@ -62,7 +62,7 @@ import {IInstantiationService} from 'vs/platform/instantiation/common/instantiat import {ServiceCollection} from 'vs/platform/instantiation/common/serviceCollection'; import {ILifecycleService} from 'vs/platform/lifecycle/common/lifecycle'; import {IMessageService} from 'vs/platform/message/common/message'; -import {ITelemetryService, Extenstions as TelemetryExtensions} from 'vs/platform/telemetry/common/telemetry'; +import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry'; import {IThreadService} from 'vs/platform/thread/common/thread'; import {MainThreadService} from 'vs/platform/thread/common/mainThreadService'; import {IStatusbarService} from 'vs/platform/statusbar/common/statusbar'; @@ -389,8 +389,6 @@ export class Workbench implements IPartService { Registry.as(ActionBarExtensions.Actionbar).setInstantiationService(this.instantiationService); Registry.as(WorkbenchExtensions.Workbench).setInstantiationService(this.instantiationService); Registry.as(EditorExtensions.Editors).setInstantiationService(this.instantiationService); - - this.instantiationService.invokeFunction(TelemetryExtensions.TelemetryAppenders.activate); } private initSettings(): void { diff --git a/src/vs/workbench/electron-browser/shell.ts b/src/vs/workbench/electron-browser/shell.ts index c8e755ef96f..e44c2d5bc5a 100644 --- a/src/vs/workbench/electron-browser/shell.ts +++ b/src/vs/workbench/electron-browser/shell.ts @@ -21,6 +21,7 @@ import {Workbench} from 'vs/workbench/browser/workbench'; import {Storage, inMemoryLocalStorageInstance} from 'vs/workbench/common/storage'; import {ITelemetryService, NullTelemetryService} from 'vs/platform/telemetry/common/telemetry'; import {ElectronTelemetryService} from 'vs/platform/telemetry/electron-browser/electronTelemetryService'; +import {AppInsightsAppender} from 'vs/platform/telemetry/node/appInsightsAppender'; import {ElectronIntegration} from 'vs/workbench/electron-browser/integration'; import {Update} from 'vs/workbench/electron-browser/update'; import {WorkspaceStats} from 'vs/platform/telemetry/common/workspaceStats'; @@ -207,7 +208,8 @@ export class WorkbenchShell { appRoot: this.configuration.env.appRoot, extensionsRoot: this.configuration.env.userExtensionsHome, version: this.configuration.env.version, - commitHash: this.configuration.env.commitHash + commitHash: this.configuration.env.commitHash, + appender: [new AppInsightsAppender(this.storageService, this.contextService)] }); } else { this.telemetryService = NullTelemetryService; diff --git a/src/vs/workbench/parts/telemetry/node/appInsights.telemetry.contribution.ts b/src/vs/workbench/parts/telemetry/node/appInsights.telemetry.contribution.ts deleted file mode 100644 index fe31472058c..00000000000 --- a/src/vs/workbench/parts/telemetry/node/appInsights.telemetry.contribution.ts +++ /dev/null @@ -1,11 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -'use strict'; - -import {Extenstions} from 'vs/platform/telemetry/common/telemetry'; -import AppInsightsTelemetryAppender = require('vs/workbench/parts/telemetry/node/nodeAppInsightsTelemetryAppender'); - -Extenstions.TelemetryAppenders.registerTelemetryAppenderDescriptor(AppInsightsTelemetryAppender.NodeAppInsightsTelemetryAppender); \ No newline at end of file diff --git a/src/vs/workbench/workbench.main.js b/src/vs/workbench/workbench.main.js index 9b4d7778dfd..50dd40c046d 100644 --- a/src/vs/workbench/workbench.main.js +++ b/src/vs/workbench/workbench.main.js @@ -74,8 +74,6 @@ define([ 'vs/workbench/parts/contentprovider/common/contentprovider.contribution', - 'vs/workbench/parts/telemetry/node/appInsights.telemetry.contribution', - 'vs/workbench/parts/themes/electron-browser/themes.contribution', 'vs/workbench/parts/feedback/electron-browser/feedback.contribution', From ba2c2242e78e36c6da27d78462649acea2e63bf7 Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 6 May 2016 13:00:30 +0200 Subject: [PATCH 082/297] fixes #4935 --- src/vs/workbench/parts/debug/browser/debugViewer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/parts/debug/browser/debugViewer.ts b/src/vs/workbench/parts/debug/browser/debugViewer.ts index 0561bcd2b3b..ac626c494ee 100644 --- a/src/vs/workbench/parts/debug/browser/debugViewer.ts +++ b/src/vs/workbench/parts/debug/browser/debugViewer.ts @@ -988,7 +988,7 @@ export class BreakpointsRenderer implements tree.IRenderer { data.checkbox.checked = breakpoint.enabled; data.actionBar.context = breakpoint; - const debugActive = this.debugService.state === debug.State.Running || this.debugService.state === debug.State.Stopped; + const debugActive = this.debugService.state === debug.State.Running || this.debugService.state === debug.State.Stopped || this.debugService.state === debug.State.Initializing; if (debugActive && !breakpoint.verified) { tree.addTraits('disabled', [breakpoint]); if (breakpoint.message) { From e9bc6350743b3b4ede45c64f1f0c7560630f6f02 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 6 May 2016 13:01:03 +0200 Subject: [PATCH 083/297] More cleanup in editor options --- src/vs/base/browser/ui/list/listView.ts | 5 +- .../browser/ui/scrollbar/abstractScrollbar.ts | 5 +- .../ui/scrollbar/horizontalScrollbar.ts | 7 +- .../browser/ui/scrollbar/scrollableElement.ts | 7 +- .../ui/scrollbar/scrollableElementOptions.ts | 14 ++-- .../scrollbarVisibilityController.ts | 26 ++----- .../browser/ui/scrollbar/verticalScrollbar.ts | 5 +- .../quickopen/browser/quickOpenWidget.ts | 3 +- src/vs/base/parts/tree/browser/tree.ts | 4 +- src/vs/base/parts/tree/browser/treeView.ts | 11 +-- .../common/config/commonEditorConfig.ts | 69 ++++++------------- src/vs/editor/common/editorCommon.ts | 60 ++++++++++++++-- .../browser/quickFixSelectionWidget.ts | 3 +- .../browser/parts/editor/binaryDiffEditor.ts | 5 +- 14 files changed, 120 insertions(+), 104 deletions(-) diff --git a/src/vs/base/browser/ui/list/listView.ts b/src/vs/base/browser/ui/list/listView.ts index ff584114ea9..72a72ee37e0 100644 --- a/src/vs/base/browser/ui/list/listView.ts +++ b/src/vs/base/browser/ui/list/listView.ts @@ -8,6 +8,7 @@ import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { Gesture } from 'vs/base/browser/touch'; import * as DOM from 'vs/base/browser/dom'; import { ScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement'; +import { ScrollbarVisibility } from 'vs/base/browser/ui/scrollbar/scrollableElementOptions'; import { RangeMap, IRange } from './rangeMap'; import { IDelegate, IRenderer } from './list'; import { RowCache, IRow } from './rowCache'; @@ -88,8 +89,8 @@ export class ListView implements IDisposable { this.scrollableElement = new ScrollableElement(this.rowsContainer, { canUseTranslate3d: false, - horizontal: 'hidden', - vertical: 'auto', + horizontal: ScrollbarVisibility.Hidden, + vertical: ScrollbarVisibility.Auto, useShadows: false, saveLastScrollTimeOnClassName: 'monaco-list-row' }); diff --git a/src/vs/base/browser/ui/scrollbar/abstractScrollbar.ts b/src/vs/base/browser/ui/scrollbar/abstractScrollbar.ts index c5b108a3f1c..2a9099717e1 100644 --- a/src/vs/base/browser/ui/scrollbar/abstractScrollbar.ts +++ b/src/vs/base/browser/ui/scrollbar/abstractScrollbar.ts @@ -12,8 +12,9 @@ import {Widget} from 'vs/base/browser/ui/widget'; import {FastDomNode, createFastDomNode} from 'vs/base/browser/styleMutator'; import {ScrollbarState} from 'vs/base/browser/ui/scrollbar/scrollbarState'; import {ScrollbarArrow, ScrollbarArrowOptions} from 'vs/base/browser/ui/scrollbar/scrollbarArrow'; -import {Visibility, ScrollbarVisibilityController} from 'vs/base/browser/ui/scrollbar/scrollbarVisibilityController'; +import {ScrollbarVisibilityController} from 'vs/base/browser/ui/scrollbar/scrollbarVisibilityController'; import {Scrollable} from 'vs/base/common/scrollable'; +import {ScrollbarVisibility} from 'vs/base/browser/ui/scrollbar/scrollableElementOptions'; /** * The orthogonal distance to the slider at which dragging "resets". This implements "snapping" @@ -37,7 +38,7 @@ export interface AbstractScrollbarOptions { lazyRender:boolean; host: ScrollbarHost; scrollbarState: ScrollbarState; - visibility: Visibility; + visibility: ScrollbarVisibility; extraScrollbarClassName: string; scrollable: Scrollable; } diff --git a/src/vs/base/browser/ui/scrollbar/horizontalScrollbar.ts b/src/vs/base/browser/ui/scrollbar/horizontalScrollbar.ts index 0481ccbefbb..11dd28aaa88 100644 --- a/src/vs/base/browser/ui/scrollbar/horizontalScrollbar.ts +++ b/src/vs/base/browser/ui/scrollbar/horizontalScrollbar.ts @@ -7,11 +7,10 @@ import {AbstractScrollbar, ScrollbarHost, IMouseMoveEventData} from 'vs/base/browser/ui/scrollbar/abstractScrollbar'; import {IMouseEvent, StandardMouseWheelEvent} from 'vs/base/browser/mouseEvent'; import {IDomNodePosition} from 'vs/base/browser/dom'; -import {ScrollableElementResolvedOptions} from 'vs/base/browser/ui/scrollbar/scrollableElementOptions'; +import {ScrollbarVisibility, ScrollableElementResolvedOptions} from 'vs/base/browser/ui/scrollbar/scrollableElementOptions'; import {Scrollable, ScrollEvent} from 'vs/base/common/scrollable'; import {ScrollbarState} from 'vs/base/browser/ui/scrollbar/scrollbarState'; import {ARROW_IMG_SIZE} from 'vs/base/browser/ui/scrollbar/scrollbarArrow'; -import {Visibility} from 'vs/base/browser/ui/scrollbar/scrollbarVisibilityController'; export class HorizontalScrollbar extends AbstractScrollbar { @@ -22,8 +21,8 @@ export class HorizontalScrollbar extends AbstractScrollbar { host: host, scrollbarState: new ScrollbarState( (options.horizontalHasArrows ? options.arrowSize : 0), - (options.horizontal === Visibility.Hidden ? 0 : options.horizontalScrollbarSize), - (options.vertical === Visibility.Hidden ? 0 : options.verticalScrollbarSize) + (options.horizontal === ScrollbarVisibility.Hidden ? 0 : options.horizontalScrollbarSize), + (options.vertical === ScrollbarVisibility.Hidden ? 0 : options.verticalScrollbarSize) ), visibility: options.horizontal, extraScrollbarClassName: 'horizontal', diff --git a/src/vs/base/browser/ui/scrollbar/scrollableElement.ts b/src/vs/base/browser/ui/scrollbar/scrollableElement.ts index 7bbb8abf995..1bd24149f75 100644 --- a/src/vs/base/browser/ui/scrollbar/scrollableElement.ts +++ b/src/vs/base/browser/ui/scrollbar/scrollableElement.ts @@ -12,8 +12,7 @@ import * as Platform from 'vs/base/common/platform'; import {StandardMouseWheelEvent, IMouseEvent} from 'vs/base/browser/mouseEvent'; import {HorizontalScrollbar} from 'vs/base/browser/ui/scrollbar/horizontalScrollbar'; import {VerticalScrollbar} from 'vs/base/browser/ui/scrollbar/verticalScrollbar'; -import {ScrollableElementCreationOptions, ScrollableElementChangeOptions, ScrollableElementResolvedOptions} from 'vs/base/browser/ui/scrollbar/scrollableElementOptions'; -import {visibilityFromString} from 'vs/base/browser/ui/scrollbar/scrollbarVisibilityController'; +import {ScrollbarVisibility, ScrollableElementCreationOptions, ScrollableElementChangeOptions, ScrollableElementResolvedOptions} from 'vs/base/browser/ui/scrollbar/scrollableElementOptions'; import {IDisposable, dispose} from 'vs/base/common/lifecycle'; import {Scrollable, ScrollEvent, INewScrollState} from 'vs/base/common/scrollable'; import {Widget} from 'vs/base/browser/ui/widget'; @@ -411,12 +410,12 @@ function resolveOptions(opts: ScrollableElementCreationOptions): ScrollableEleme listenOnDomNode: (typeof opts.listenOnDomNode !== 'undefined' ? opts.listenOnDomNode : null), - horizontal: visibilityFromString(typeof opts.horizontal !== 'undefined' ? opts.horizontal : 'auto'), + horizontal: (typeof opts.horizontal !== 'undefined' ? opts.horizontal : ScrollbarVisibility.Auto), horizontalScrollbarSize: (typeof opts.horizontalScrollbarSize !== 'undefined' ? opts.horizontalScrollbarSize : 10), horizontalSliderSize: (typeof opts.horizontalSliderSize !== 'undefined' ? opts.horizontalSliderSize : 0), horizontalHasArrows: (typeof opts.horizontalHasArrows !== 'undefined' ? opts.horizontalHasArrows : false), - vertical: visibilityFromString(typeof opts.vertical !== 'undefined' ? opts.vertical : 'auto'), + vertical: (typeof opts.vertical !== 'undefined' ? opts.vertical : ScrollbarVisibility.Auto), verticalScrollbarSize: (typeof opts.verticalScrollbarSize !== 'undefined' ? opts.verticalScrollbarSize : 10), verticalHasArrows: (typeof opts.verticalHasArrows !== 'undefined' ? opts.verticalHasArrows : false), verticalSliderSize: (typeof opts.verticalSliderSize !== 'undefined' ? opts.verticalSliderSize : 0), diff --git a/src/vs/base/browser/ui/scrollbar/scrollableElementOptions.ts b/src/vs/base/browser/ui/scrollbar/scrollableElementOptions.ts index 28a8b53f153..164413ccc83 100644 --- a/src/vs/base/browser/ui/scrollbar/scrollableElementOptions.ts +++ b/src/vs/base/browser/ui/scrollbar/scrollableElementOptions.ts @@ -4,7 +4,11 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import {Visibility} from 'vs/base/browser/ui/scrollbar/scrollbarVisibilityController'; +export enum ScrollbarVisibility { + Auto = 1, + Hidden = 2, + Visible = 3 +} export interface ScrollableElementCreationOptions { /** @@ -55,7 +59,7 @@ export interface ScrollableElementCreationOptions { * Accepted values: 'auto' (on mouse over), 'visible' (always visible), 'hidden' (never visible) * Defaults to 'auto'. */ - horizontal?: string; + horizontal?: ScrollbarVisibility; /** * Height (in px) of the horizontal scrollbar. * Defaults to 10. @@ -76,7 +80,7 @@ export interface ScrollableElementCreationOptions { * Accepted values: 'auto' (on mouse over), 'visible' (always visible), 'hidden' (never visible) * Defaults to 'auto'. */ - vertical?: string; + vertical?: ScrollbarVisibility; /** * Width (in px) of the vertical scrollbar. * Defaults to 10. @@ -114,11 +118,11 @@ export interface ScrollableElementResolvedOptions { mouseWheelScrollSensitivity: number; arrowSize: number; listenOnDomNode: HTMLElement; - horizontal: Visibility; + horizontal: ScrollbarVisibility; horizontalScrollbarSize: number; horizontalSliderSize: number; horizontalHasArrows: boolean; - vertical: Visibility; + vertical: ScrollbarVisibility; verticalScrollbarSize: number; verticalSliderSize: number; verticalHasArrows: boolean; diff --git a/src/vs/base/browser/ui/scrollbar/scrollbarVisibilityController.ts b/src/vs/base/browser/ui/scrollbar/scrollbarVisibilityController.ts index bddbc6bb6e3..9b1141d5041 100644 --- a/src/vs/base/browser/ui/scrollbar/scrollbarVisibilityController.ts +++ b/src/vs/base/browser/ui/scrollbar/scrollbarVisibilityController.ts @@ -7,26 +7,10 @@ import {Disposable} from 'vs/base/common/lifecycle'; import {TimeoutTimer} from 'vs/base/common/async'; import {FastDomNode} from 'vs/base/browser/styleMutator'; - -export enum Visibility { - Auto, - Hidden, - Visible -} - -export function visibilityFromString(visibility: string): Visibility { - switch (visibility) { - case 'hidden': - return Visibility.Hidden; - case 'visible': - return Visibility.Visible; - default: - return Visibility.Auto; - } -} +import {ScrollbarVisibility} from 'vs/base/browser/ui/scrollbar/scrollableElementOptions'; export class ScrollbarVisibilityController extends Disposable { - private _visibility: Visibility; + private _visibility: ScrollbarVisibility; private _visibleClassName: string; private _invisibleClassName: string; private _domNode: FastDomNode; @@ -35,7 +19,7 @@ export class ScrollbarVisibilityController extends Disposable { private _isVisible: boolean; private _revealTimer: TimeoutTimer; - constructor(visibility: Visibility, visibleClassName: string, invisibleClassName: string) { + constructor(visibility: ScrollbarVisibility, visibleClassName: string, invisibleClassName: string) { super(); this._visibility = visibility; this._visibleClassName = visibleClassName; @@ -50,10 +34,10 @@ export class ScrollbarVisibilityController extends Disposable { // ----------------- Hide / Reveal private applyVisibilitySetting(shouldBeVisible: boolean): boolean { - if (this._visibility === Visibility.Hidden) { + if (this._visibility === ScrollbarVisibility.Hidden) { return false; } - if (this._visibility === Visibility.Visible) { + if (this._visibility === ScrollbarVisibility.Visible) { return true; } return shouldBeVisible; diff --git a/src/vs/base/browser/ui/scrollbar/verticalScrollbar.ts b/src/vs/base/browser/ui/scrollbar/verticalScrollbar.ts index 1f511d29172..a371d3895c7 100644 --- a/src/vs/base/browser/ui/scrollbar/verticalScrollbar.ts +++ b/src/vs/base/browser/ui/scrollbar/verticalScrollbar.ts @@ -7,11 +7,10 @@ import {AbstractScrollbar, ScrollbarHost, IMouseMoveEventData} from 'vs/base/browser/ui/scrollbar/abstractScrollbar'; import {IMouseEvent, StandardMouseWheelEvent} from 'vs/base/browser/mouseEvent'; import {IDomNodePosition} from 'vs/base/browser/dom'; -import {ScrollableElementResolvedOptions} from 'vs/base/browser/ui/scrollbar/scrollableElementOptions'; +import {ScrollbarVisibility, ScrollableElementResolvedOptions} from 'vs/base/browser/ui/scrollbar/scrollableElementOptions'; import {Scrollable, ScrollEvent} from 'vs/base/common/scrollable'; import {ScrollbarState} from 'vs/base/browser/ui/scrollbar/scrollbarState'; import {ARROW_IMG_SIZE} from 'vs/base/browser/ui/scrollbar/scrollbarArrow'; -import {Visibility} from 'vs/base/browser/ui/scrollbar/scrollbarVisibilityController'; export class VerticalScrollbar extends AbstractScrollbar { @@ -22,7 +21,7 @@ export class VerticalScrollbar extends AbstractScrollbar { host: host, scrollbarState: new ScrollbarState( (options.verticalHasArrows ? options.arrowSize : 0), - (options.vertical === Visibility.Hidden ? 0 : options.verticalScrollbarSize), + (options.vertical === ScrollbarVisibility.Hidden ? 0 : options.verticalScrollbarSize), // give priority to vertical scroll bar over horizontal and let it scroll all the way to the bottom 0 ), diff --git a/src/vs/base/parts/quickopen/browser/quickOpenWidget.ts b/src/vs/base/parts/quickopen/browser/quickOpenWidget.ts index 92f4304b920..97500cc6efb 100644 --- a/src/vs/base/parts/quickopen/browser/quickOpenWidget.ts +++ b/src/vs/base/parts/quickopen/browser/quickOpenWidget.ts @@ -27,6 +27,7 @@ import DOM = require('vs/base/browser/dom'); import {IActionProvider} from 'vs/base/parts/tree/browser/actionsRenderer'; import {KeyCode} from 'vs/base/common/keyCodes'; import {IDisposable,dispose} from 'vs/base/common/lifecycle'; +import {ScrollbarVisibility} from 'vs/base/browser/ui/scrollbar/scrollableElementOptions'; export interface IQuickOpenCallbacks { onOk: () => void; @@ -190,7 +191,7 @@ export class QuickOpenWidget implements IModelProvider { twistiePixels: 11, indentPixels: 0, alwaysFocused: true, - verticalScrollMode: 'visible', + verticalScrollMode: ScrollbarVisibility.Visible, ariaLabel: nls.localize('treeAriaLabel', "Quick Picker") }); diff --git a/src/vs/base/parts/tree/browser/tree.ts b/src/vs/base/parts/tree/browser/tree.ts index 07e8866f0bb..2915e3c4f9a 100644 --- a/src/vs/base/parts/tree/browser/tree.ts +++ b/src/vs/base/parts/tree/browser/tree.ts @@ -10,6 +10,7 @@ import Events = require('vs/base/common/eventEmitter'); import Mouse = require('vs/base/browser/mouseEvent'); import Keyboard = require('vs/base/browser/keyboardEvent'); import { INavigator } from 'vs/base/common/iterator'; +import { ScrollbarVisibility } from 'vs/base/browser/ui/scrollbar/scrollableElementOptions'; export interface ITree extends Events.IEventEmitter { @@ -614,8 +615,7 @@ export interface ITreeConfiguration { export interface ITreeOptions { twistiePixels?: number; indentPixels?: number; - horizontalScrollMode?: string; - verticalScrollMode?: string; + verticalScrollMode?: ScrollbarVisibility; alwaysFocused?: boolean; autoExpandSingleChildren?: boolean; bare?:boolean; diff --git a/src/vs/base/parts/tree/browser/treeView.ts b/src/vs/base/parts/tree/browser/treeView.ts index 60636cdcc65..4dc7492aaae 100644 --- a/src/vs/base/parts/tree/browser/treeView.ts +++ b/src/vs/base/parts/tree/browser/treeView.ts @@ -17,7 +17,8 @@ import Keyboard = require('vs/base/browser/keyboardEvent'); import Model = require('vs/base/parts/tree/browser/treeModel'); import dnd = require('./treeDnd'); import { ArrayIterator, MappedIterator } from 'vs/base/common/iterator'; -import ScrollableElementImpl = require('vs/base/browser/ui/scrollbar/scrollableElement'); +import { ScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement'; +import { ScrollbarVisibility } from 'vs/base/browser/ui/scrollbar/scrollableElementOptions'; import { HeightMap } from 'vs/base/parts/tree/browser/treeViewModel'; import _ = require('vs/base/parts/tree/browser/tree'); import { IViewItem } from 'vs/base/parts/tree/browser/treeViewModel'; @@ -407,7 +408,7 @@ export class TreeView extends HeightMap { private domNode: HTMLElement; private wrapper: HTMLElement; private rowsContainer: HTMLElement; - private scrollableElement: ScrollableElementImpl.ScrollableElement; + private scrollableElement: ScrollableElement; private wrapperGesture: Touch.Gesture; private msGesture: MSGesture; private lastPointerType:string; @@ -486,10 +487,10 @@ export class TreeView extends HeightMap { this.wrapper = document.createElement('div'); this.wrapper.className = 'monaco-tree-wrapper'; - this.scrollableElement = new ScrollableElementImpl.ScrollableElement(this.wrapper, { + this.scrollableElement = new ScrollableElement(this.wrapper, { canUseTranslate3d: false, - horizontal: 'hidden', - vertical: context.options.verticalScrollMode || 'auto', + horizontal: ScrollbarVisibility.Hidden, + vertical: (typeof context.options.verticalScrollMode !== 'undefined' ? context.options.verticalScrollMode : ScrollbarVisibility.Auto), useShadows: context.options.useShadows, saveLastScrollTimeOnClassName: 'monaco-tree-row' }); diff --git a/src/vs/editor/common/config/commonEditorConfig.ts b/src/vs/editor/common/config/commonEditorConfig.ts index 95321852730..a03ef0a7e43 100644 --- a/src/vs/editor/common/config/commonEditorConfig.ts +++ b/src/vs/editor/common/config/commonEditorConfig.ts @@ -14,6 +14,7 @@ import {Registry} from 'vs/platform/platform'; import {DefaultConfig, DEFAULT_INDENTATION, GOLDEN_LINE_HEIGHT_RATIO} from 'vs/editor/common/config/defaultConfig'; import * as editorCommon from 'vs/editor/common/editorCommon'; import {EditorLayoutProvider} from 'vs/editor/common/viewLayout/editorLayoutProvider'; +import {ScrollbarVisibility} from 'vs/base/browser/ui/scrollbar/scrollableElementOptions'; /** * Experimental screen reader support toggle @@ -76,7 +77,7 @@ export class InternalEditorOptions implements editorCommon.IInternalEditorOption roundedSelection:boolean; theme:string; readOnly:boolean; - scrollbar:editorCommon.IInternalEditorScrollbarOptions; + scrollbar:editorCommon.InternalEditorScrollbarOptions; overviewRulerLanes:number; cursorBlinking:string; cursorStyle:editorCommon.TextEditorCursorStyle; @@ -131,20 +132,7 @@ export class InternalEditorOptions implements editorCommon.IInternalEditorOption this.roundedSelection = Boolean(input.roundedSelection); this.theme = String(input.theme); this.readOnly = Boolean(input.readOnly); - this.scrollbar = { - arrowSize: Number(input.scrollbar.arrowSize)|0, - vertical: String(input.scrollbar.vertical), - horizontal: String(input.scrollbar.horizontal), - useShadows: Boolean(input.scrollbar.useShadows), - verticalHasArrows: Boolean(input.scrollbar.verticalHasArrows), - horizontalHasArrows: Boolean(input.scrollbar.horizontalHasArrows), - handleMouseWheel: Boolean(input.scrollbar.handleMouseWheel), - horizontalScrollbarSize: Number(input.scrollbar.horizontalScrollbarSize)|0, - horizontalSliderSize: Number(input.scrollbar.horizontalSliderSize)|0, - verticalScrollbarSize: Number(input.scrollbar.verticalScrollbarSize)|0, - verticalSliderSize: Number(input.scrollbar.verticalSliderSize)|0, - mouseWheelScrollSensitivity: Number(input.scrollbar.mouseWheelScrollSensitivity), - }; + this.scrollbar = input.scrollbar.clone(); this.overviewRulerLanes = Number(input.overviewRulerLanes)|0; this.cursorBlinking = String(input.cursorBlinking); this.cursorStyle = Number(input.cursorStyle)|0; @@ -348,12 +336,24 @@ class InternalEditorOptionsHelper { }; } - private static _sanitizeScrollbarOpts(raw:editorCommon.IEditorScrollbarOptions, mouseWheelScrollSensitivity:number): editorCommon.IInternalEditorScrollbarOptions { + private static _sanitizeScrollbarOpts(raw:editorCommon.IEditorScrollbarOptions, mouseWheelScrollSensitivity:number): editorCommon.InternalEditorScrollbarOptions { + + var visibilityFromString = (visibility: string) => { + switch (visibility) { + case 'hidden': + return ScrollbarVisibility.Hidden; + case 'visible': + return ScrollbarVisibility.Visible; + default: + return ScrollbarVisibility.Auto; + } + }; + let horizontalScrollbarSize = toIntegerWithDefault(raw.horizontalScrollbarSize, 10); let verticalScrollbarSize = toIntegerWithDefault(raw.verticalScrollbarSize, 14); - return { - vertical: toStringSet(raw.vertical, ['auto', 'visible', 'hidden'], 'auto'), - horizontal: toStringSet(raw.horizontal, ['auto', 'visible', 'hidden'], 'auto'), + return new editorCommon.InternalEditorScrollbarOptions({ + vertical: visibilityFromString(raw.vertical), + horizontal: visibilityFromString(raw.horizontal), arrowSize: toIntegerWithDefault(raw.arrowSize, 11), useShadows: toBooleanWithDefault(raw.useShadows, true), @@ -369,7 +369,7 @@ class InternalEditorOptionsHelper { handleMouseWheel: toBooleanWithDefault(raw.handleMouseWheel, true), mouseWheelScrollSensitivity: mouseWheelScrollSensitivity - }; + }); } public static createConfigurationChangedEvent(prevOpts:InternalEditorOptions, newOpts:InternalEditorOptions): editorCommon.IConfigurationChangedEvent { @@ -387,7 +387,7 @@ class InternalEditorOptionsHelper { roundedSelection: (prevOpts.roundedSelection !== newOpts.roundedSelection), theme: (prevOpts.theme !== newOpts.theme), readOnly: (prevOpts.readOnly !== newOpts.readOnly), - scrollbar: (!this._scrollbarOptsEqual(prevOpts.scrollbar, newOpts.scrollbar)), + scrollbar: (!prevOpts.scrollbar.equals(newOpts.scrollbar)), overviewRulerLanes: (prevOpts.overviewRulerLanes !== newOpts.overviewRulerLanes), cursorBlinking: (prevOpts.cursorBlinking !== newOpts.cursorBlinking), cursorStyle: (prevOpts.cursorStyle !== newOpts.cursorStyle), @@ -432,23 +432,6 @@ class InternalEditorOptionsHelper { }; } - private static _scrollbarOptsEqual(a:editorCommon.IInternalEditorScrollbarOptions, b:editorCommon.IInternalEditorScrollbarOptions): boolean { - return ( - a.arrowSize === b.arrowSize - && a.vertical === b.vertical - && a.horizontal === b.horizontal - && a.useShadows === b.useShadows - && a.verticalHasArrows === b.verticalHasArrows - && a.horizontalHasArrows === b.horizontalHasArrows - && a.handleMouseWheel === b.handleMouseWheel - && a.horizontalScrollbarSize === b.horizontalScrollbarSize - && a.horizontalSliderSize === b.horizontalSliderSize - && a.verticalScrollbarSize === b.verticalScrollbarSize - && a.verticalSliderSize === b.verticalSliderSize - && a.mouseWheelScrollSensitivity === b.mouseWheelScrollSensitivity - ); - } - private static _wrappingInfoEqual(a:editorCommon.IEditorWrappingInfo, b:editorCommon.IEditorWrappingInfo): boolean { return ( a.isViewportWrapping === b.isViewportWrapping @@ -540,16 +523,6 @@ function toIntegerWithDefault(source:any, defaultValue:number): number { return toInteger(source); } -function toStringSet(source:any, allowedValues:string[], defaultValue:string): string { - if (typeof source !== 'string') { - return defaultValue; - } - if (allowedValues.indexOf(source) === -1) { - return defaultValue; - } - return source; -} - interface IValidatedIndentationOptions { tabSizeIsAuto: boolean; tabSize: number; diff --git a/src/vs/editor/common/editorCommon.ts b/src/vs/editor/common/editorCommon.ts index 0556264111f..f697faa6b8c 100644 --- a/src/vs/editor/common/editorCommon.ts +++ b/src/vs/editor/common/editorCommon.ts @@ -14,6 +14,7 @@ import {TPromise} from 'vs/base/common/winjs.base'; import {IInstantiationService, IConstructorSignature1, IConstructorSignature2} from 'vs/platform/instantiation/common/instantiation'; import {ILineContext, IMode, IModeTransition, IToken} from 'vs/editor/common/modes'; import {ViewLineToken} from 'vs/editor/common/core/viewLineToken'; +import {ScrollbarVisibility} from 'vs/base/browser/ui/scrollbar/scrollableElementOptions'; export type KeyCode = KeyCode; export type KeyMod = KeyMod; @@ -561,10 +562,12 @@ export interface IDiffEditorOptions extends IEditorOptions { originalEditable?: boolean; } -export interface IInternalEditorScrollbarOptions { +export class InternalEditorScrollbarOptions { + _internalEditorScrollbarOptionsBrand: void; + arrowSize:number; - vertical:string; - horizontal:string; + vertical:ScrollbarVisibility; + horizontal:ScrollbarVisibility; useShadows:boolean; verticalHasArrows:boolean; horizontalHasArrows:boolean; @@ -574,6 +577,55 @@ export interface IInternalEditorScrollbarOptions { verticalScrollbarSize: number; verticalSliderSize: number; mouseWheelScrollSensitivity: number; + + constructor(source:{ + arrowSize:number; + vertical:ScrollbarVisibility; + horizontal:ScrollbarVisibility; + useShadows:boolean; + verticalHasArrows:boolean; + horizontalHasArrows:boolean; + handleMouseWheel: boolean; + horizontalScrollbarSize: number; + horizontalSliderSize: number; + verticalScrollbarSize: number; + verticalSliderSize: number; + mouseWheelScrollSensitivity: number; + }) { + this.arrowSize = source.arrowSize|0; + this.vertical = source.vertical|0; + this.horizontal = source.horizontal|0; + this.useShadows = Boolean(source.useShadows); + this.verticalHasArrows = Boolean(source.verticalHasArrows); + this.horizontalHasArrows = Boolean(source.horizontalHasArrows); + this.handleMouseWheel = Boolean(source.handleMouseWheel); + this.horizontalScrollbarSize = source.horizontalScrollbarSize|0; + this.horizontalSliderSize = source.horizontalSliderSize|0; + this.verticalScrollbarSize = source.verticalScrollbarSize|0; + this.verticalSliderSize = source.verticalSliderSize|0; + this.mouseWheelScrollSensitivity = Number(source.mouseWheelScrollSensitivity); + } + + public equals(other:InternalEditorScrollbarOptions): boolean { + return ( + this.arrowSize === other.arrowSize + && this.vertical === other.vertical + && this.horizontal === other.horizontal + && this.useShadows === other.useShadows + && this.verticalHasArrows === other.verticalHasArrows + && this.horizontalHasArrows === other.horizontalHasArrows + && this.handleMouseWheel === other.handleMouseWheel + && this.horizontalScrollbarSize === other.horizontalScrollbarSize + && this.horizontalSliderSize === other.horizontalSliderSize + && this.verticalScrollbarSize === other.verticalScrollbarSize + && this.verticalSliderSize === other.verticalSliderSize + && this.mouseWheelScrollSensitivity === other.mouseWheelScrollSensitivity + ); + } + + public clone(): InternalEditorScrollbarOptions { + return new InternalEditorScrollbarOptions(this); + } } export interface IEditorWrappingInfo { @@ -599,7 +651,7 @@ export interface IInternalEditorOptions { roundedSelection:boolean; theme:string; readOnly:boolean; - scrollbar:IInternalEditorScrollbarOptions; + scrollbar:InternalEditorScrollbarOptions; overviewRulerLanes:number; cursorBlinking:string; cursorStyle:TextEditorCursorStyle; diff --git a/src/vs/editor/contrib/quickFix/browser/quickFixSelectionWidget.ts b/src/vs/editor/contrib/quickFix/browser/quickFixSelectionWidget.ts index 3b4f5407272..1b09c084ae4 100644 --- a/src/vs/editor/contrib/quickFix/browser/quickFixSelectionWidget.ts +++ b/src/vs/editor/contrib/quickFix/browser/quickFixSelectionWidget.ts @@ -22,6 +22,7 @@ import {ContentWidgetPositionPreference, ICodeEditor, IContentWidget, IContentWi import {IQuickFix2} from '../common/quickFix'; import {QuickFixModel} from './quickFixModel'; import {alert} from 'vs/base/browser/ui/aria/aria'; +import {ScrollbarVisibility} from 'vs/base/browser/ui/scrollbar/scrollableElementOptions'; var $ = dom.emmet; @@ -253,7 +254,7 @@ export class QuickFixSelectionWidget implements IContentWidget { }, { twistiePixels: 0, alwaysFocused: true, - verticalScrollMode: 'visible', + verticalScrollMode: ScrollbarVisibility.Visible, useShadows: false, ariaLabel: nls.localize('treeAriaLabel', "Quick Fix") }); diff --git a/src/vs/workbench/browser/parts/editor/binaryDiffEditor.ts b/src/vs/workbench/browser/parts/editor/binaryDiffEditor.ts index 82e50e1642b..c2f2a4eee80 100644 --- a/src/vs/workbench/browser/parts/editor/binaryDiffEditor.ts +++ b/src/vs/workbench/browser/parts/editor/binaryDiffEditor.ts @@ -19,6 +19,7 @@ import {BinaryEditorModel} from 'vs/workbench/common/editor/binaryEditorModel'; import {DiffEditorModel} from 'vs/workbench/common/editor/diffEditorModel'; import {IWorkbenchEditorService} from 'vs/workbench/services/editor/common/editorService'; import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry'; +import {ScrollbarVisibility} from 'vs/base/browser/ui/scrollbar/scrollableElementOptions'; /** * An implementation of editor for diffing binary files like images or videos. @@ -58,7 +59,7 @@ export class BinaryResourceDiffEditor extends BaseEditor implements IVerticalSas this.leftBinaryContainer.tabindex(0); // enable focus support from the editor part (do not remove) // Left Custom Scrollbars - this.leftScrollbar = new DomScrollableElement(leftBinaryContainerElement, { canUseTranslate3d: false, horizontal: 'hidden', vertical: 'hidden' }); + this.leftScrollbar = new DomScrollableElement(leftBinaryContainerElement, { canUseTranslate3d: false, horizontal: ScrollbarVisibility.Hidden, vertical: ScrollbarVisibility.Hidden }); parent.getHTMLElement().appendChild(this.leftScrollbar.getDomNode()); $(this.leftScrollbar.getDomNode()).addClass('binarydiff-left'); @@ -76,7 +77,7 @@ export class BinaryResourceDiffEditor extends BaseEditor implements IVerticalSas this.rightBinaryContainer.tabindex(0); // enable focus support from the editor part (do not remove) // Right Custom Scrollbars - this.rightScrollbar = new DomScrollableElement(rightBinaryContainerElement, { canUseTranslate3d: false,horizontal: 'hidden', vertical: 'hidden' }); + this.rightScrollbar = new DomScrollableElement(rightBinaryContainerElement, { canUseTranslate3d: false, horizontal: ScrollbarVisibility.Hidden, vertical: ScrollbarVisibility.Hidden }); parent.getHTMLElement().appendChild(this.rightScrollbar.getDomNode()); $(this.rightScrollbar.getDomNode()).addClass('binarydiff-right'); } From b2286a1f6db5a289149521a1f602ab282d3664b4 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 6 May 2016 13:49:22 +0200 Subject: [PATCH 084/297] Further grouping of resolved editor options --- .../browser/controller/keyboardHandler.ts | 4 +- .../editor/browser/controller/mouseHandler.ts | 2 +- .../editor/browser/controller/mouseTarget.ts | 8 +- src/vs/editor/browser/view/viewImpl.ts | 16 +- .../browser/viewLayout/layoutProvider.ts | 2 +- .../browser/viewLayout/scrollManager.ts | 8 +- .../viewParts/glyphMargin/glyphMargin.ts | 6 +- .../viewParts/lineNumbers/lineNumbers.ts | 6 +- .../browser/viewParts/lines/viewLine.ts | 18 +- .../browser/viewParts/lines/viewLines.ts | 6 +- .../overviewRuler/decorationsOverviewRuler.ts | 10 +- .../editor/browser/viewParts/rulers/rulers.ts | 6 +- .../scrollDecoration/scrollDecoration.ts | 6 +- .../viewParts/selections/selections.ts | 6 +- .../viewParts/viewCursors/viewCursor.ts | 6 +- .../viewParts/viewCursors/viewCursors.ts | 14 +- .../editor/browser/widget/diffEditorWidget.ts | 6 +- .../common/config/commonEditorConfig.ts | 122 +++-------- src/vs/editor/common/editorCommon.ts | 205 ++++++++++++++---- .../editor/common/viewLayout/linesLayout.ts | 6 +- .../common/viewModel/viewModelCursors.ts | 2 +- .../editor/common/viewModel/viewModelImpl.ts | 4 +- .../contrib/indentation/common/indentation.ts | 2 +- .../workbench/api/node/mainThreadEditors.ts | 2 +- 24 files changed, 266 insertions(+), 207 deletions(-) diff --git a/src/vs/editor/browser/controller/keyboardHandler.ts b/src/vs/editor/browser/controller/keyboardHandler.ts index 97598308345..9f5c72f46bc 100644 --- a/src/vs/editor/browser/controller/keyboardHandler.ts +++ b/src/vs/editor/browser/controller/keyboardHandler.ts @@ -311,7 +311,7 @@ export class KeyboardHandler extends ViewEventHandler implements IDisposable { if (GlobalScreenReaderNVDA.getValue()) { return TextAreaStrategy.NVDA; } - if (this._context.configuration.editor.experimentalScreenReader) { + if (this._context.configuration.editor.viewInfo.experimentalScreenReader) { return TextAreaStrategy.NVDA; } return TextAreaStrategy.IENarrator; @@ -326,7 +326,7 @@ export class KeyboardHandler extends ViewEventHandler implements IDisposable { if (e.fontInfo) { Configuration.applyFontInfoSlow(this.textArea.actual, this._context.configuration.editor.fontInfo); } - if (e.experimentalScreenReader) { + if (e.viewInfo.experimentalScreenReader) { this.textAreaHandler.setStrategy(this._getStrategy()); } return false; diff --git a/src/vs/editor/browser/controller/mouseHandler.ts b/src/vs/editor/browser/controller/mouseHandler.ts index 90a9caef4ed..ad6558a40a2 100644 --- a/src/vs/editor/browser/controller/mouseHandler.ts +++ b/src/vs/editor/browser/controller/mouseHandler.ts @@ -260,7 +260,7 @@ export class MouseHandler extends ViewEventHandler implements IDisposable { let targetIsContent = (t.type === editorCommon.MouseTargetType.CONTENT_TEXT || t.type === editorCommon.MouseTargetType.CONTENT_EMPTY); let targetIsGutter = (t.type === editorCommon.MouseTargetType.GUTTER_GLYPH_MARGIN || t.type === editorCommon.MouseTargetType.GUTTER_LINE_NUMBERS || t.type === editorCommon.MouseTargetType.GUTTER_LINE_DECORATIONS); let targetIsLineNumbers = (t.type === editorCommon.MouseTargetType.GUTTER_LINE_NUMBERS); - let selectOnLineNumbers = this._context.configuration.editor.selectOnLineNumbers; + let selectOnLineNumbers = this._context.configuration.editor.viewInfo.selectOnLineNumbers; let targetIsViewZone = (t.type === editorCommon.MouseTargetType.CONTENT_VIEW_ZONE || t.type === editorCommon.MouseTargetType.GUTTER_VIEW_ZONE); let shouldHandle = e.leftButton; diff --git a/src/vs/editor/browser/controller/mouseTarget.ts b/src/vs/editor/browser/controller/mouseTarget.ts index c2d0923506a..d6d8615c3f9 100644 --- a/src/vs/editor/browser/controller/mouseTarget.ts +++ b/src/vs/editor/browser/controller/mouseTarget.ts @@ -213,9 +213,9 @@ export class MouseTargetFactory { // Is it the textarea cover? if (REGEX.IS_TEXTAREA_COVER.test(path)) { - if (this._context.configuration.editor.glyphMargin) { + if (this._context.configuration.editor.viewInfo.glyphMargin) { return this.createMouseTargetFromGlyphMargin(t, mouseVerticalOffset, mouseColumn); - } else if (this._context.configuration.editor.lineNumbers) { + } else if (this._context.configuration.editor.viewInfo.lineNumbers) { return this.createMouseTargetFromLineNumbers(t, mouseVerticalOffset, mouseColumn); } else { return this.createMouseTargetFromLinesDecorationsChild(t, mouseVerticalOffset, mouseColumn); @@ -359,8 +359,8 @@ export class MouseTargetFactory { if (adjustedPosy <= editorContent.top) { adjustedPosy = editorContent.top + 1; } - if (adjustedPosy >= editorContent.top + this._context.configuration.editor.observedOuterHeight) { - adjustedPosy = editorContent.top + this._context.configuration.editor.observedOuterHeight - 1; + if (adjustedPosy >= editorContent.top + this._context.configuration.editor.layoutInfo.height) { + adjustedPosy = editorContent.top + this._context.configuration.editor.layoutInfo.height - 1; } var hitx = e.posx - document.body.scrollLeft; diff --git a/src/vs/editor/browser/view/viewImpl.ts b/src/vs/editor/browser/view/viewImpl.ts index 977b282def2..574c007fee2 100644 --- a/src/vs/editor/browser/view/viewImpl.ts +++ b/src/vs/editor/browser/view/viewImpl.ts @@ -111,7 +111,7 @@ export class View extends ViewEventHandler implements editorBrowser.IView, IDisp this.linesContent = document.createElement('div'); this.linesContent.className = editorBrowser.ClassNames.LINES_CONTENT + ' monaco-editor-background'; this.domNode = document.createElement('div'); - this.domNode.className = configuration.editor.editorClassName; + this.domNode.className = configuration.editor.viewInfo.editorClassName; this.overflowGuardContainer = document.createElement('div'); this.overflowGuardContainer.className = editorBrowser.ClassNames.OVERFLOW_GUARD; @@ -177,7 +177,7 @@ export class View extends ViewEventHandler implements editorBrowser.IView, IDisp this.textArea.setAttribute('autocorrect', 'off'); this.textArea.setAttribute('autocapitalize', 'off'); this.textArea.setAttribute('spellcheck', 'false'); - this.textArea.setAttribute('aria-label', this._context.configuration.editor.ariaLabel); + this.textArea.setAttribute('aria-label', this._context.configuration.editor.viewInfo.ariaLabel); this.textArea.setAttribute('role', 'textbox'); this.textArea.setAttribute('aria-multiline', 'true'); this.textArea.setAttribute('aria-haspopup', 'false'); @@ -193,10 +193,10 @@ export class View extends ViewEventHandler implements editorBrowser.IView, IDisp // (there have been reports of tiny blinking cursors) // (in WebKit the textarea is 1px by 1px because it cannot handle input to a 0x0 textarea) this.textAreaCover = document.createElement('div'); - if (this._context.configuration.editor.glyphMargin) { + if (this._context.configuration.editor.viewInfo.glyphMargin) { this.textAreaCover.className = 'monaco-editor-background ' + editorBrowser.ClassNames.GLYPH_MARGIN + ' ' + editorBrowser.ClassNames.TEXTAREA_COVER; } else { - if (this._context.configuration.editor.lineNumbers) { + if (this._context.configuration.editor.viewInfo.lineNumbers) { this.textAreaCover.className = 'monaco-editor-background ' + editorBrowser.ClassNames.LINE_NUMBERS + ' ' + editorBrowser.ClassNames.TEXTAREA_COVER; } else { this.textAreaCover.className = 'monaco-editor-background ' + editorBrowser.ClassNames.TEXTAREA_COVER; @@ -448,11 +448,11 @@ export class View extends ViewEventHandler implements editorBrowser.IView, IDisp return false; } public onConfigurationChanged(e: editorCommon.IConfigurationChangedEvent): boolean { - if (e.editorClassName) { - this.domNode.className = this._context.configuration.editor.editorClassName; + if (e.viewInfo.editorClassName) { + this.domNode.className = this._context.configuration.editor.viewInfo.editorClassName; } - if (e.ariaLabel) { - this.textArea.setAttribute('aria-label', this._context.configuration.editor.ariaLabel); + if (e.viewInfo.ariaLabel) { + this.textArea.setAttribute('aria-label', this._context.configuration.editor.viewInfo.ariaLabel); } return false; } diff --git a/src/vs/editor/browser/viewLayout/layoutProvider.ts b/src/vs/editor/browser/viewLayout/layoutProvider.ts index baf3ef73bc0..38f3e4f0a6e 100644 --- a/src/vs/editor/browser/viewLayout/layoutProvider.ts +++ b/src/vs/editor/browser/viewLayout/layoutProvider.ts @@ -267,7 +267,7 @@ export class LayoutProvider extends ViewEventHandler implements IDisposable, ILa public getTotalHeight(): number { var reserveHorizontalScrollbarHeight = 0; if (this.scrollManager.getScrollWidth() > this.scrollManager.getWidth()) { - reserveHorizontalScrollbarHeight = this.configuration.editor.scrollbar.horizontalScrollbarSize; + reserveHorizontalScrollbarHeight = this.configuration.editor.viewInfo.scrollbar.horizontalScrollbarSize; } return this.linesLayout.getTotalHeight(this.getCurrentViewport(), reserveHorizontalScrollbarHeight); } diff --git a/src/vs/editor/browser/viewLayout/scrollManager.ts b/src/vs/editor/browser/viewLayout/scrollManager.ts index 5dcf4b03bbf..a84107bdecd 100644 --- a/src/vs/editor/browser/viewLayout/scrollManager.ts +++ b/src/vs/editor/browser/viewLayout/scrollManager.ts @@ -33,7 +33,7 @@ export class ScrollManager implements IDisposable { this.privateViewEventBus = privateViewEventBus; this.linesContent = linesContent; - var configScrollbarOpts = this.configuration.editor.scrollbar; + var configScrollbarOpts = this.configuration.editor.viewInfo.scrollbar; var scrollbarOptions:ScrollableElementCreationOptions = { canUseTranslate3d: true, @@ -64,11 +64,11 @@ export class ScrollManager implements IDisposable { this.toDispose.push(this.configuration.onDidChange((e:IConfigurationChangedEvent) => { this.scrollbar.updateClassName(this.configuration.editor.theme); - if (e.scrollbar) { + if (e.viewInfo.scrollbar) { let newOpts:ScrollableElementChangeOptions = { canUseTranslate3d: true, - handleMouseWheel: this.configuration.editor.scrollbar.handleMouseWheel, - mouseWheelScrollSensitivity: this.configuration.editor.scrollbar.mouseWheelScrollSensitivity + handleMouseWheel: this.configuration.editor.viewInfo.scrollbar.handleMouseWheel, + mouseWheelScrollSensitivity: this.configuration.editor.viewInfo.scrollbar.mouseWheelScrollSensitivity }; this.scrollbar.updateOptions(newOpts); } diff --git a/src/vs/editor/browser/viewParts/glyphMargin/glyphMargin.ts b/src/vs/editor/browser/viewParts/glyphMargin/glyphMargin.ts index ea5a5c9d323..e6ebfa2963c 100644 --- a/src/vs/editor/browser/viewParts/glyphMargin/glyphMargin.ts +++ b/src/vs/editor/browser/viewParts/glyphMargin/glyphMargin.ts @@ -87,7 +87,7 @@ export class GlyphMarginOverlay extends DedupOverlay { super(); this._context = context; this._lineHeight = this._context.configuration.editor.lineHeight; - this._glyphMargin = this._context.configuration.editor.glyphMargin; + this._glyphMargin = this._context.configuration.editor.viewInfo.glyphMargin; this._glyphMarginLeft = 0; this._glyphMarginWidth = 0; this._renderResult = null; @@ -130,8 +130,8 @@ export class GlyphMarginOverlay extends DedupOverlay { if (e.lineHeight) { this._lineHeight = this._context.configuration.editor.lineHeight; } - if (e.glyphMargin) { - this._glyphMargin = this._context.configuration.editor.glyphMargin; + if (e.viewInfo.glyphMargin) { + this._glyphMargin = this._context.configuration.editor.viewInfo.glyphMargin; } return true; } diff --git a/src/vs/editor/browser/viewParts/lineNumbers/lineNumbers.ts b/src/vs/editor/browser/viewParts/lineNumbers/lineNumbers.ts index 50aaa13d5c9..00fe1d34a68 100644 --- a/src/vs/editor/browser/viewParts/lineNumbers/lineNumbers.ts +++ b/src/vs/editor/browser/viewParts/lineNumbers/lineNumbers.ts @@ -26,7 +26,7 @@ export class LineNumbersOverlay extends DynamicViewOverlay { super(); this._context = context; this._lineHeight = this._context.configuration.editor.lineHeight; - this._lineNumbers = this._context.configuration.editor.lineNumbers; + this._lineNumbers = this._context.configuration.editor.viewInfo.lineNumbers; this._lineNumbersLeft = 0; this._lineNumbersWidth = 0; this._renderResult = null; @@ -69,8 +69,8 @@ export class LineNumbersOverlay extends DynamicViewOverlay { if (e.lineHeight) { this._lineHeight = this._context.configuration.editor.lineHeight; } - if (e.lineNumbers) { - this._lineNumbers = this._context.configuration.editor.lineNumbers; + if (e.viewInfo.lineNumbers) { + this._lineNumbers = this._context.configuration.editor.viewInfo.lineNumbers; } return true; } diff --git a/src/vs/editor/browser/viewParts/lines/viewLine.ts b/src/vs/editor/browser/viewParts/lines/viewLine.ts index 8ccbd5bcb05..4bbfbdddfca 100644 --- a/src/vs/editor/browser/viewParts/lines/viewLine.ts +++ b/src/vs/editor/browser/viewParts/lines/viewLine.ts @@ -38,11 +38,11 @@ export class ViewLine implements IVisibleLineData { constructor(context:ViewContext) { this._context = context; - this._renderWhitespace = this._context.configuration.editor.renderWhitespace; - this._indentGuides = this._context.configuration.editor.indentGuides; + this._renderWhitespace = this._context.configuration.editor.viewInfo.renderWhitespace; + this._indentGuides = this._context.configuration.editor.viewInfo.indentGuides; this._spaceWidth = this._context.configuration.editor.fontInfo.spaceWidth; this._lineHeight = this._context.configuration.editor.lineHeight; - this._stopRenderingLineAfter = this._context.configuration.editor.stopRenderingLineAfter; + this._stopRenderingLineAfter = this._context.configuration.editor.viewInfo.stopRenderingLineAfter; this._fontLigatures = this._context.configuration.editor.fontLigatures; this._domNode = null; @@ -84,11 +84,11 @@ export class ViewLine implements IVisibleLineData { this._isMaybeInvalid = true; } public onConfigurationChanged(e:IConfigurationChangedEvent): void { - if (e.renderWhitespace) { - this._renderWhitespace = this._context.configuration.editor.renderWhitespace; + if (e.viewInfo.renderWhitespace) { + this._renderWhitespace = this._context.configuration.editor.viewInfo.renderWhitespace; } - if (e.indentGuides) { - this._indentGuides = this._context.configuration.editor.indentGuides; + if (e.viewInfo.indentGuides) { + this._indentGuides = this._context.configuration.editor.viewInfo.indentGuides; } if (e.fontInfo) { this._spaceWidth = this._context.configuration.editor.fontInfo.spaceWidth; @@ -96,8 +96,8 @@ export class ViewLine implements IVisibleLineData { if (e.lineHeight) { this._lineHeight = this._context.configuration.editor.lineHeight; } - if (e.stopRenderingLineAfter) { - this._stopRenderingLineAfter = this._context.configuration.editor.stopRenderingLineAfter; + if (e.viewInfo.stopRenderingLineAfter) { + this._stopRenderingLineAfter = this._context.configuration.editor.viewInfo.stopRenderingLineAfter; } if (e.fontLigatures) { this._fontLigatures = this._context.configuration.editor.fontLigatures; diff --git a/src/vs/editor/browser/viewParts/lines/viewLines.ts b/src/vs/editor/browser/viewParts/lines/viewLines.ts index 26f212f10c0..2e38399174e 100644 --- a/src/vs/editor/browser/viewParts/lines/viewLines.ts +++ b/src/vs/editor/browser/viewParts/lines/viewLines.ts @@ -77,7 +77,7 @@ export class ViewLines extends ViewLayer { super(context); this._lineHeight = this._context.configuration.editor.lineHeight; this._isViewportWrapping = this._context.configuration.editor.wrappingInfo.isViewportWrapping; - this._revealHorizontalRightPadding = this._context.configuration.editor.revealHorizontalRightPadding; + this._revealHorizontalRightPadding = this._context.configuration.editor.viewInfo.revealHorizontalRightPadding; this._layoutProvider = layoutProvider; this.domNode.setClassName(ClassNames.VIEW_LINES); Configuration.applyFontInfo(this.domNode, this._context.configuration.editor.fontInfo); @@ -119,8 +119,8 @@ export class ViewLines extends ViewLayer { if (e.wrappingInfo) { this._isViewportWrapping = this._context.configuration.editor.wrappingInfo.isViewportWrapping; } - if (e.revealHorizontalRightPadding) { - this._revealHorizontalRightPadding = this._context.configuration.editor.revealHorizontalRightPadding; + if (e.viewInfo.revealHorizontalRightPadding) { + this._revealHorizontalRightPadding = this._context.configuration.editor.viewInfo.revealHorizontalRightPadding; } if (e.fontInfo) { Configuration.applyFontInfo(this.domNode, this._context.configuration.editor.fontInfo); diff --git a/src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler.ts b/src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler.ts index 94e294216ed..fb458999068 100644 --- a/src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler.ts +++ b/src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler.ts @@ -41,7 +41,7 @@ export class DecorationsOverviewRuler extends ViewPart { DecorationsOverviewRuler.DECORATION_HEIGHT, getVerticalOffsetForLine ); - this._overviewRuler.setLanesCount(this._context.configuration.editor.overviewRulerLanes, false); + this._overviewRuler.setLanesCount(this._context.configuration.editor.viewInfo.overviewRulerLanes, false); let theme = this._context.configuration.editor.theme; this._overviewRuler.setUseDarkColor(!themes.isLightTheme(theme), false); @@ -49,7 +49,7 @@ export class DecorationsOverviewRuler extends ViewPart { this._zonesFromDecorations = []; this._shouldUpdateCursorPosition = true; - this._hideCursor = this._context.configuration.editor.hideCursorInOverviewRuler; + this._hideCursor = this._context.configuration.editor.viewInfo.hideCursorInOverviewRuler; this._zonesFromCursors = []; this._cursorPositions = []; @@ -71,7 +71,7 @@ export class DecorationsOverviewRuler extends ViewPart { public onConfigurationChanged(e:editorCommon.IConfigurationChangedEvent): boolean { var prevLanesCount = this._overviewRuler.getLanesCount(); - var newLanesCount = this._context.configuration.editor.overviewRulerLanes; + var newLanesCount = this._context.configuration.editor.viewInfo.overviewRulerLanes; var shouldRender = false; @@ -85,8 +85,8 @@ export class DecorationsOverviewRuler extends ViewPart { shouldRender = true; } - if (e.hideCursorInOverviewRuler) { - this._hideCursor = this._context.configuration.editor.hideCursorInOverviewRuler; + if (e.viewInfo.hideCursorInOverviewRuler) { + this._hideCursor = this._context.configuration.editor.viewInfo.hideCursorInOverviewRuler; this._shouldUpdateCursorPosition = true; shouldRender = true; } diff --git a/src/vs/editor/browser/viewParts/rulers/rulers.ts b/src/vs/editor/browser/viewParts/rulers/rulers.ts index 8487ed00c6b..5613af40616 100644 --- a/src/vs/editor/browser/viewParts/rulers/rulers.ts +++ b/src/vs/editor/browser/viewParts/rulers/rulers.ts @@ -26,7 +26,7 @@ export class Rulers extends ViewPart { this._layoutProvider = layoutProvider; this.domNode = document.createElement('div'); this.domNode.className = 'view-rulers'; - this._rulers = this._context.configuration.editor.rulers; + this._rulers = this._context.configuration.editor.viewInfo.rulers; this._height = this._context.configuration.editor.layoutInfo.contentHeight; this._typicalHalfwidthCharacterWidth = this._context.configuration.editor.fontInfo.typicalHalfwidthCharacterWidth; } @@ -38,8 +38,8 @@ export class Rulers extends ViewPart { // --- begin event handlers public onConfigurationChanged(e: editorCommon.IConfigurationChangedEvent): boolean { - if (e.rulers || e.layoutInfo || e.fontInfo) { - this._rulers = this._context.configuration.editor.rulers; + if (e.viewInfo.rulers || e.layoutInfo || e.fontInfo) { + this._rulers = this._context.configuration.editor.viewInfo.rulers; this._height = this._context.configuration.editor.layoutInfo.contentHeight; this._typicalHalfwidthCharacterWidth = this._context.configuration.editor.fontInfo.typicalHalfwidthCharacterWidth; return true; diff --git a/src/vs/editor/browser/viewParts/scrollDecoration/scrollDecoration.ts b/src/vs/editor/browser/viewParts/scrollDecoration/scrollDecoration.ts index f605f5ffeb8..129acbd0a66 100644 --- a/src/vs/editor/browser/viewParts/scrollDecoration/scrollDecoration.ts +++ b/src/vs/editor/browser/viewParts/scrollDecoration/scrollDecoration.ts @@ -28,7 +28,7 @@ export class ScrollDecorationViewPart extends ViewPart { this._scrollTop = 0; this._width = 0; this._shouldShow = false; - this._useShadows = this._context.configuration.editor.scrollbar.useShadows; + this._useShadows = this._context.configuration.editor.viewInfo.scrollbar.useShadows; this._domNode = document.createElement('div'); } @@ -48,8 +48,8 @@ export class ScrollDecorationViewPart extends ViewPart { // --- begin event handlers public onConfigurationChanged(e: IConfigurationChangedEvent): boolean { - if (e.scrollbar) { - this._useShadows = this._context.configuration.editor.scrollbar.useShadows; + if (e.viewInfo.scrollbar) { + this._useShadows = this._context.configuration.editor.viewInfo.scrollbar.useShadows; } return this._updateShouldShow(); } diff --git a/src/vs/editor/browser/viewParts/selections/selections.ts b/src/vs/editor/browser/viewParts/selections/selections.ts index 4d864f7ed1b..e15c9d1851c 100644 --- a/src/vs/editor/browser/viewParts/selections/selections.ts +++ b/src/vs/editor/browser/viewParts/selections/selections.ts @@ -85,7 +85,7 @@ export class SelectionsOverlay extends DynamicViewOverlay { super(); this._context = context; this._lineHeight = this._context.configuration.editor.lineHeight; - this._roundedSelection = this._context.configuration.editor.roundedSelection; + this._roundedSelection = this._context.configuration.editor.viewInfo.roundedSelection; this._selections = []; this._renderResult = null; this._context.addEventHandler(this); @@ -131,8 +131,8 @@ export class SelectionsOverlay extends DynamicViewOverlay { if (e.lineHeight) { this._lineHeight = this._context.configuration.editor.lineHeight; } - if (e.roundedSelection) { - this._roundedSelection = this._context.configuration.editor.roundedSelection; + if (e.viewInfo.roundedSelection) { + this._roundedSelection = this._context.configuration.editor.viewInfo.roundedSelection; } return true; } diff --git a/src/vs/editor/browser/viewParts/viewCursors/viewCursor.ts b/src/vs/editor/browser/viewParts/viewCursors/viewCursor.ts index 9efe240bbd8..0a9243a3d78 100644 --- a/src/vs/editor/browser/viewParts/viewCursors/viewCursor.ts +++ b/src/vs/editor/browser/viewParts/viewCursors/viewCursor.ts @@ -25,7 +25,7 @@ export class ViewCursor { constructor(context:ViewContext, isSecondary:boolean) { this._context = context; - this._cursorStyle = this._context.configuration.editor.cursorStyle; + this._cursorStyle = this._context.configuration.editor.viewInfo.cursorStyle; this._lineHeight = this._context.configuration.editor.lineHeight; this._lastRenderedContent = ''; @@ -105,8 +105,8 @@ export class ViewCursor { if (e.lineHeight) { this._lineHeight = this._context.configuration.editor.lineHeight; } - if (e.cursorStyle) { - this._cursorStyle = this._context.configuration.editor.cursorStyle; + if (e.viewInfo.cursorStyle) { + this._cursorStyle = this._context.configuration.editor.viewInfo.cursorStyle; } if (e.fontInfo) { Configuration.applyFontInfo(this._domNode, this._context.configuration.editor.fontInfo); diff --git a/src/vs/editor/browser/viewParts/viewCursors/viewCursors.ts b/src/vs/editor/browser/viewParts/viewCursors/viewCursors.ts index fd9622f642d..472a2eec8f0 100644 --- a/src/vs/editor/browser/viewParts/viewCursors/viewCursors.ts +++ b/src/vs/editor/browser/viewParts/viewCursors/viewCursors.ts @@ -44,8 +44,8 @@ export class ViewCursors extends ViewPart { super(context); this._readOnly = this._context.configuration.editor.readOnly; - this._cursorBlinking = this._context.configuration.editor.cursorBlinking; - this._cursorStyle = this._context.configuration.editor.cursorStyle; + this._cursorBlinking = this._context.configuration.editor.viewInfo.cursorBlinking; + this._cursorStyle = this._context.configuration.editor.viewInfo.cursorStyle; this._primaryCursor = new ViewCursor(this._context, false); this._secondaryCursors = []; @@ -146,16 +146,16 @@ export class ViewCursors extends ViewPart { if (e.readOnly) { this._readOnly = this._context.configuration.editor.readOnly; } - if (e.cursorBlinking) { - this._cursorBlinking = this._context.configuration.editor.cursorBlinking; + if (e.viewInfo.cursorBlinking) { + this._cursorBlinking = this._context.configuration.editor.viewInfo.cursorBlinking; } - if (e.cursorStyle) { - this._cursorStyle = this._context.configuration.editor.cursorStyle; + if (e.viewInfo.cursorStyle) { + this._cursorStyle = this._context.configuration.editor.viewInfo.cursorStyle; } this._primaryCursor.onConfigurationChanged(e); this._updateBlinking(); - if (e.cursorStyle) { + if (e.viewInfo.cursorStyle) { this._updateDomClassName(); } for (var i = 0, len = this._secondaryCursors.length; i < len; i++) { diff --git a/src/vs/editor/browser/widget/diffEditorWidget.ts b/src/vs/editor/browser/widget/diffEditorWidget.ts index 83bf01e5247..67d7245a3f6 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget.ts @@ -1778,14 +1778,14 @@ class InlineViewZonesComputer extends ViewZonesComputer { let lineTokens = new ViewLineTokens([new ViewLineToken(0, '')], 0, lineContent.length); - let parts = createLineParts(lineNumber, 1, lineContent, tabSize, lineTokens, decorations, config.renderWhitespace, config.indentGuides); + let parts = createLineParts(lineNumber, 1, lineContent, tabSize, lineTokens, decorations, config.viewInfo.renderWhitespace, config.viewInfo.indentGuides); let r = renderLine(new RenderLineInput( lineContent, tabSize, config.fontInfo.spaceWidth, - config.stopRenderingLineAfter, - config.renderWhitespace, + config.viewInfo.stopRenderingLineAfter, + config.viewInfo.renderWhitespace, parts.getParts() )); diff --git a/src/vs/editor/common/config/commonEditorConfig.ts b/src/vs/editor/common/config/commonEditorConfig.ts index a03ef0a7e43..fcffb4cc4cb 100644 --- a/src/vs/editor/common/config/commonEditorConfig.ts +++ b/src/vs/editor/common/config/commonEditorConfig.ts @@ -65,32 +65,17 @@ export class ConfigurationWithDefaults { export class InternalEditorOptions implements editorCommon.IInternalEditorOptions { _internalEditorOptionsBrand: void; - experimentalScreenReader: boolean; - rulers: number[]; wordSeparators: string; selectionClipboard: boolean; - ariaLabel: string; - lineNumbers:any; - selectOnLineNumbers:boolean; - glyphMargin:boolean; - revealHorizontalRightPadding:number; - roundedSelection:boolean; theme:string; readOnly:boolean; - scrollbar:editorCommon.InternalEditorScrollbarOptions; - overviewRulerLanes:number; - cursorBlinking:string; - cursorStyle:editorCommon.TextEditorCursorStyle; fontLigatures:boolean; - hideCursorInOverviewRuler:boolean; - scrollBeyondLastLine:boolean; wrappingIndent: editorCommon.WrappingIndent; wordWrapBreakBeforeCharacters: string; wordWrapBreakAfterCharacters: string; wordWrapBreakObtrusiveCharacters: string; tabFocusMode:boolean; stopLineTokenizationAfter:number; - stopRenderingLineAfter: number; longLineBoundary:number; forcedTokenizationBoundary:number; hover:boolean; @@ -106,46 +91,27 @@ export class InternalEditorOptions implements editorCommon.IInternalEditorOption outlineMarkers: boolean; referenceInfos: boolean; folding: boolean; - renderWhitespace: boolean; - indentGuides: boolean; useTabStops: boolean; trimAutoWhitespace: boolean; layoutInfo: editorCommon.EditorLayoutInfo; fontInfo: editorCommon.FontInfo; - editorClassName: string; + viewInfo: editorCommon.InternalEditorViewOptions; wrappingInfo: editorCommon.IEditorWrappingInfo; - observedOuterWidth:number; - observedOuterHeight:number; lineHeight:number; pageSize:number; constructor(input:editorCommon.IInternalEditorOptions) { - this.experimentalScreenReader = Boolean(input.experimentalScreenReader); - this.rulers = Array.prototype.slice.call(input.rulers, 0); this.wordSeparators = String(input.wordSeparators); this.selectionClipboard = Boolean(input.selectionClipboard); - this.ariaLabel = String(input.ariaLabel); - this.lineNumbers = input.lineNumbers || false; - this.selectOnLineNumbers = Boolean(input.selectOnLineNumbers); - this.glyphMargin = Boolean(input.glyphMargin); - this.revealHorizontalRightPadding = Number(input.revealHorizontalRightPadding)|0; - this.roundedSelection = Boolean(input.roundedSelection); this.theme = String(input.theme); this.readOnly = Boolean(input.readOnly); - this.scrollbar = input.scrollbar.clone(); - this.overviewRulerLanes = Number(input.overviewRulerLanes)|0; - this.cursorBlinking = String(input.cursorBlinking); - this.cursorStyle = Number(input.cursorStyle)|0; this.fontLigatures = Boolean(input.fontLigatures); - this.hideCursorInOverviewRuler = Boolean(input.hideCursorInOverviewRuler); - this.scrollBeyondLastLine = Boolean(input.scrollBeyondLastLine); this.wrappingIndent = input.wrappingIndent; this.wordWrapBreakBeforeCharacters = String(input.wordWrapBreakBeforeCharacters); this.wordWrapBreakAfterCharacters = String(input.wordWrapBreakAfterCharacters); this.wordWrapBreakObtrusiveCharacters = String(input.wordWrapBreakObtrusiveCharacters); this.tabFocusMode = Boolean(input.tabFocusMode); this.stopLineTokenizationAfter = Number(input.stopLineTokenizationAfter)|0; - this.stopRenderingLineAfter = Number(input.stopRenderingLineAfter)|0; this.longLineBoundary = Number(input.longLineBoundary)|0; this.forcedTokenizationBoundary = Number(input.forcedTokenizationBoundary)|0; this.hover = Boolean(input.hover); @@ -161,19 +127,15 @@ export class InternalEditorOptions implements editorCommon.IInternalEditorOption this.outlineMarkers = Boolean(input.outlineMarkers); this.referenceInfos = Boolean(input.referenceInfos); this.folding = Boolean(input.folding); - this.renderWhitespace = Boolean(input.renderWhitespace); - this.indentGuides = Boolean(input.indentGuides); this.useTabStops = Boolean(input.useTabStops); this.trimAutoWhitespace = Boolean(input.trimAutoWhitespace); this.layoutInfo = input.layoutInfo.clone(); this.fontInfo = input.fontInfo.clone(); - this.editorClassName = input.editorClassName; + this.viewInfo = input.viewInfo.clone(); this.wrappingInfo = { isViewportWrapping: Boolean(input.wrappingInfo.isViewportWrapping), wrappingColumn: Number(input.wrappingInfo.wrappingColumn)|0, }; - this.observedOuterWidth = Number(input.observedOuterWidth)|0; - this.observedOuterHeight = Number(input.observedOuterHeight)|0; this.lineHeight = Number(input.lineHeight)|0; this.pageSize = Number(input.pageSize)|0; } @@ -274,34 +236,40 @@ class InternalEditorOptionsHelper { tabFocusMode = true; } - return { - // ---- Options that are transparent - get no massaging + let viewInfo = new editorCommon.InternalEditorViewOptions({ + experimentalScreenReader: toBoolean(opts.experimentalScreenReader), + rulers: toSortedIntegerArray(opts.rulers), + ariaLabel: String(opts.ariaLabel), lineNumbers: lineNumbers, selectOnLineNumbers: toBoolean(opts.selectOnLineNumbers), glyphMargin: glyphMargin, revealHorizontalRightPadding: toInteger(opts.revealHorizontalRightPadding, 0), roundedSelection: toBoolean(opts.roundedSelection), - theme: opts.theme, - readOnly: readOnly, - scrollbar: scrollbar, overviewRulerLanes: toInteger(opts.overviewRulerLanes, 0, 3), cursorBlinking: opts.cursorBlinking, - experimentalScreenReader: toBoolean(opts.experimentalScreenReader), - rulers: toSortedIntegerArray(opts.rulers), - wordSeparators: String(opts.wordSeparators), - selectionClipboard: toBoolean(opts.selectionClipboard), - ariaLabel: String(opts.ariaLabel), cursorStyle: cursorStyleFromString(opts.cursorStyle), - fontLigatures: toBoolean(opts.fontLigatures), hideCursorInOverviewRuler: toBoolean(opts.hideCursorInOverviewRuler), scrollBeyondLastLine: toBoolean(opts.scrollBeyondLastLine), + editorClassName: editorClassName, + stopRenderingLineAfter: stopRenderingLineAfter, + renderWhitespace: toBoolean(opts.renderWhitespace), + indentGuides: toBoolean(opts.indentGuides), + scrollbar: scrollbar, + }); + + return { + // ---- Options that are transparent - get no massaging + theme: opts.theme, + readOnly: readOnly, + wordSeparators: String(opts.wordSeparators), + selectionClipboard: toBoolean(opts.selectionClipboard), + fontLigatures: toBoolean(opts.fontLigatures), wrappingIndent: wrappingIndentFromString(opts.wrappingIndent), wordWrapBreakBeforeCharacters: opts.wordWrapBreakBeforeCharacters, wordWrapBreakAfterCharacters: opts.wordWrapBreakAfterCharacters, wordWrapBreakObtrusiveCharacters: opts.wordWrapBreakObtrusiveCharacters, tabFocusMode: tabFocusMode, stopLineTokenizationAfter: stopLineTokenizationAfter, - stopRenderingLineAfter: stopRenderingLineAfter, longLineBoundary: toInteger(opts.longLineBoundary), forcedTokenizationBoundary: toInteger(opts.forcedTokenizationBoundary), @@ -318,19 +286,14 @@ class InternalEditorOptionsHelper { outlineMarkers: toBoolean(opts.outlineMarkers), referenceInfos: toBoolean(opts.referenceInfos), folding: toBoolean(opts.folding), - renderWhitespace: toBoolean(opts.renderWhitespace), - indentGuides: toBoolean(opts.indentGuides), useTabStops: toBoolean(opts.useTabStops), trimAutoWhitespace: toBoolean(opts.trimAutoWhitespace), layoutInfo: layoutInfo, fontInfo: fontInfo, - editorClassName: editorClassName, + viewInfo: viewInfo, wrappingInfo: wrappingInfo, - observedOuterWidth: outerWidth, - observedOuterHeight: outerHeight, - lineHeight: fontInfo.lineHeight, // todo -> duplicated in styling pageSize: pageSize, }; @@ -374,33 +337,18 @@ class InternalEditorOptionsHelper { public static createConfigurationChangedEvent(prevOpts:InternalEditorOptions, newOpts:InternalEditorOptions): editorCommon.IConfigurationChangedEvent { return { - experimentalScreenReader: (prevOpts.experimentalScreenReader !== newOpts.experimentalScreenReader), - rulers: (!this._numberArraysEqual(prevOpts.rulers, newOpts.rulers)), wordSeparators: (prevOpts.wordSeparators !== newOpts.wordSeparators), selectionClipboard: (prevOpts.selectionClipboard !== newOpts.selectionClipboard), - ariaLabel: (prevOpts.ariaLabel !== newOpts.ariaLabel), - lineNumbers: (prevOpts.lineNumbers !== newOpts.lineNumbers), - selectOnLineNumbers: (prevOpts.selectOnLineNumbers !== newOpts.selectOnLineNumbers), - glyphMargin: (prevOpts.glyphMargin !== newOpts.glyphMargin), - revealHorizontalRightPadding: (prevOpts.revealHorizontalRightPadding !== newOpts.revealHorizontalRightPadding), - roundedSelection: (prevOpts.roundedSelection !== newOpts.roundedSelection), theme: (prevOpts.theme !== newOpts.theme), readOnly: (prevOpts.readOnly !== newOpts.readOnly), - scrollbar: (!prevOpts.scrollbar.equals(newOpts.scrollbar)), - overviewRulerLanes: (prevOpts.overviewRulerLanes !== newOpts.overviewRulerLanes), - cursorBlinking: (prevOpts.cursorBlinking !== newOpts.cursorBlinking), - cursorStyle: (prevOpts.cursorStyle !== newOpts.cursorStyle), fontLigatures: (prevOpts.fontLigatures !== newOpts.fontLigatures), - hideCursorInOverviewRuler: (prevOpts.hideCursorInOverviewRuler !== newOpts.hideCursorInOverviewRuler), - scrollBeyondLastLine: (prevOpts.scrollBeyondLastLine !== newOpts.scrollBeyondLastLine), wrappingIndent: (prevOpts.wrappingIndent !== newOpts.wrappingIndent), wordWrapBreakBeforeCharacters: (prevOpts.wordWrapBreakBeforeCharacters !== newOpts.wordWrapBreakBeforeCharacters), wordWrapBreakAfterCharacters: (prevOpts.wordWrapBreakAfterCharacters !== newOpts.wordWrapBreakAfterCharacters), wordWrapBreakObtrusiveCharacters:(prevOpts.wordWrapBreakObtrusiveCharacters !== newOpts.wordWrapBreakObtrusiveCharacters), tabFocusMode: (prevOpts.tabFocusMode !== newOpts.tabFocusMode), stopLineTokenizationAfter: (prevOpts.stopLineTokenizationAfter !== newOpts.stopLineTokenizationAfter), - stopRenderingLineAfter: (prevOpts.stopRenderingLineAfter !== newOpts.stopRenderingLineAfter), longLineBoundary: (prevOpts.longLineBoundary !== newOpts.longLineBoundary), forcedTokenizationBoundary: (prevOpts.forcedTokenizationBoundary !== newOpts.forcedTokenizationBoundary), @@ -416,17 +364,13 @@ class InternalEditorOptionsHelper { outlineMarkers: (prevOpts.outlineMarkers !== newOpts.outlineMarkers), referenceInfos: (prevOpts.referenceInfos !== newOpts.referenceInfos), folding: (prevOpts.folding !== newOpts.folding), - renderWhitespace: (prevOpts.renderWhitespace !== newOpts.renderWhitespace), - indentGuides: (prevOpts.indentGuides !== newOpts.indentGuides), useTabStops: (prevOpts.useTabStops !== newOpts.useTabStops), trimAutoWhitespace: (prevOpts.trimAutoWhitespace !== newOpts.trimAutoWhitespace), layoutInfo: (!prevOpts.layoutInfo.equals(newOpts.layoutInfo)), fontInfo: (!prevOpts.fontInfo.equals(newOpts.fontInfo)), - editorClassName: (prevOpts.editorClassName !== newOpts.editorClassName), + viewInfo: prevOpts.viewInfo.createChangeEvent(newOpts.viewInfo), wrappingInfo: (!this._wrappingInfoEqual(prevOpts.wrappingInfo, newOpts.wrappingInfo)), - observedOuterWidth: (prevOpts.observedOuterWidth !== newOpts.observedOuterWidth), - observedOuterHeight: (prevOpts.observedOuterHeight !== newOpts.observedOuterHeight), lineHeight: (prevOpts.lineHeight !== newOpts.lineHeight), pageSize: (prevOpts.pageSize !== newOpts.pageSize), }; @@ -439,17 +383,6 @@ class InternalEditorOptionsHelper { ); } - private static _numberArraysEqual(a:number[], b:number[]): boolean { - if (a.length !== b.length) { - return false; - } - for (let i = 0; i < a.length; i++) { - if (a[i] !== b[i]) { - return false; - } - } - return true; - } } function toBoolean(value:any): boolean { @@ -577,7 +510,16 @@ export abstract class CommonEditorConfiguration extends Disposable implements ed let keys = Object.keys(changeEvent); for (let i = 0, len = keys.length; i < len; i++) { let key = keys[i]; - if (changeEvent[key]) { + if (changeEvent[key] === true) { + hasChanged = true; + break; + } + } + + keys = Object.keys(changeEvent.viewInfo); + for (let i = 0, len = keys.length; i < len; i++) { + let key = keys[i]; + if (changeEvent[key] === true) { hasChanged = true; break; } diff --git a/src/vs/editor/common/editorCommon.ts b/src/vs/editor/common/editorCommon.ts index f697faa6b8c..b396e507b32 100644 --- a/src/vs/editor/common/editorCommon.ts +++ b/src/vs/editor/common/editorCommon.ts @@ -633,38 +633,183 @@ export interface IEditorWrappingInfo { wrappingColumn: number; } -/** - * Internal configuration options (transformed or computed) for the editor. - */ -export interface IInternalEditorOptions { +export class InternalEditorViewOptions { experimentalScreenReader: boolean; rulers: number[]; - wordSeparators: string; - selectionClipboard: boolean; ariaLabel: string; - - // ---- Options that are transparent - get no massaging lineNumbers:any; selectOnLineNumbers:boolean; glyphMargin:boolean; revealHorizontalRightPadding:number; roundedSelection:boolean; - theme:string; - readOnly:boolean; - scrollbar:InternalEditorScrollbarOptions; overviewRulerLanes:number; cursorBlinking:string; cursorStyle:TextEditorCursorStyle; - fontLigatures:boolean; hideCursorInOverviewRuler:boolean; scrollBeyondLastLine:boolean; + editorClassName: string; + stopRenderingLineAfter: number; + renderWhitespace: boolean; + indentGuides: boolean; + scrollbar:InternalEditorScrollbarOptions; + + constructor(source:{ + experimentalScreenReader: boolean; + rulers: number[]; + ariaLabel: string; + lineNumbers:any; + selectOnLineNumbers:boolean; + glyphMargin:boolean; + revealHorizontalRightPadding:number; + roundedSelection:boolean; + overviewRulerLanes:number; + cursorBlinking:string; + cursorStyle:TextEditorCursorStyle; + hideCursorInOverviewRuler:boolean; + scrollBeyondLastLine:boolean; + editorClassName: string; + stopRenderingLineAfter: number; + renderWhitespace: boolean; + indentGuides: boolean; + scrollbar:InternalEditorScrollbarOptions; + }) { + this.experimentalScreenReader = Boolean(source.experimentalScreenReader); + this.rulers = InternalEditorViewOptions._toSortedIntegerArray(source.rulers); + this.ariaLabel = String(source.ariaLabel); + this.lineNumbers = source.lineNumbers; + this.selectOnLineNumbers = Boolean(source.selectOnLineNumbers); + this.glyphMargin = Boolean(source.glyphMargin); + this.revealHorizontalRightPadding = source.revealHorizontalRightPadding|0; + this.roundedSelection = Boolean(source.roundedSelection); + this.overviewRulerLanes = source.overviewRulerLanes|0; + this.cursorBlinking = String(source.cursorBlinking); + this.cursorStyle = source.cursorStyle|0; + this.hideCursorInOverviewRuler = Boolean(source.hideCursorInOverviewRuler); + this.scrollBeyondLastLine = Boolean(source.scrollBeyondLastLine); + this.editorClassName = String(source.editorClassName); + this.stopRenderingLineAfter = source.stopRenderingLineAfter|0; + this.renderWhitespace = Boolean(source.renderWhitespace); + this.indentGuides = Boolean(source.indentGuides); + this.scrollbar = source.scrollbar.clone(); + } + + private static _toSortedIntegerArray(source:any): number[] { + if (!Array.isArray(source)) { + return []; + } + let arrSource = source; + let result = arrSource.map(el => { + let r = parseInt(el, 10); + if (isNaN(r)) { + return 0; + } + return r; + }); + result.sort(); + return result; + } + + private static _numberArraysEqual(a:number[], b:number[]): boolean { + if (a.length !== b.length) { + return false; + } + for (let i = 0; i < a.length; i++) { + if (a[i] !== b[i]) { + return false; + } + } + return true; + } + + public equals(other:InternalEditorViewOptions): boolean { + return ( + this.experimentalScreenReader === other.experimentalScreenReader + && InternalEditorViewOptions._numberArraysEqual(this.rulers, other.rulers) + && this.ariaLabel === other.ariaLabel + && this.lineNumbers === other.lineNumbers + && this.selectOnLineNumbers === other.selectOnLineNumbers + && this.glyphMargin === other.glyphMargin + && this.revealHorizontalRightPadding === other.revealHorizontalRightPadding + && this.roundedSelection === other.roundedSelection + && this.overviewRulerLanes === other.overviewRulerLanes + && this.cursorBlinking === other.cursorBlinking + && this.cursorStyle === other.cursorStyle + && this.hideCursorInOverviewRuler === other.hideCursorInOverviewRuler + && this.scrollBeyondLastLine === other.scrollBeyondLastLine + && this.editorClassName === other.editorClassName + && this.stopRenderingLineAfter === other.stopRenderingLineAfter + && this.renderWhitespace === other.renderWhitespace + && this.indentGuides === other.indentGuides + && this.scrollbar.equals(other.scrollbar) + ); + } + + public createChangeEvent(newOpts:InternalEditorViewOptions): IViewConfigurationChangedEvent { + return { + experimentalScreenReader: this.experimentalScreenReader !== newOpts.experimentalScreenReader, + rulers: (!InternalEditorViewOptions._numberArraysEqual(this.rulers, newOpts.rulers)), + ariaLabel: this.ariaLabel !== newOpts.ariaLabel, + lineNumbers: this.lineNumbers !== newOpts.lineNumbers, + selectOnLineNumbers: this.selectOnLineNumbers !== newOpts.selectOnLineNumbers, + glyphMargin: this.glyphMargin !== newOpts.glyphMargin, + revealHorizontalRightPadding: this.revealHorizontalRightPadding !== newOpts.revealHorizontalRightPadding, + roundedSelection: this.roundedSelection !== newOpts.roundedSelection, + overviewRulerLanes: this.overviewRulerLanes !== newOpts.overviewRulerLanes, + cursorBlinking: this.cursorBlinking !== newOpts.cursorBlinking, + cursorStyle: this.cursorStyle !== newOpts.cursorStyle, + hideCursorInOverviewRuler: this.hideCursorInOverviewRuler !== newOpts.hideCursorInOverviewRuler, + scrollBeyondLastLine: this.scrollBeyondLastLine !== newOpts.scrollBeyondLastLine, + editorClassName: this.editorClassName !== newOpts.editorClassName, + stopRenderingLineAfter: this.stopRenderingLineAfter !== newOpts.stopRenderingLineAfter, + renderWhitespace: this.renderWhitespace !== newOpts.renderWhitespace, + indentGuides: this.indentGuides !== newOpts.indentGuides, + scrollbar: (!this.scrollbar.equals(newOpts.scrollbar)), + }; + } + + public clone(): InternalEditorViewOptions { + return new InternalEditorViewOptions(this); + } +} + +export interface IViewConfigurationChangedEvent { + experimentalScreenReader: boolean; + rulers: boolean; + ariaLabel: boolean; + lineNumbers: boolean; + selectOnLineNumbers: boolean; + glyphMargin: boolean; + revealHorizontalRightPadding: boolean; + roundedSelection: boolean; + overviewRulerLanes: boolean; + cursorBlinking: boolean; + cursorStyle: boolean; + hideCursorInOverviewRuler: boolean; + scrollBeyondLastLine: boolean; + editorClassName: boolean; + stopRenderingLineAfter: boolean; + renderWhitespace: boolean; + indentGuides: boolean; + scrollbar: boolean; +} + +/** + * Internal configuration options (transformed or computed) for the editor. + */ +export interface IInternalEditorOptions { + wordSeparators: string; + selectionClipboard: boolean; + + // ---- Options that are transparent - get no massaging + theme:string; + readOnly:boolean; + fontLigatures:boolean; wrappingIndent: WrappingIndent; wordWrapBreakBeforeCharacters: string; wordWrapBreakAfterCharacters: string; wordWrapBreakObtrusiveCharacters: string; tabFocusMode:boolean; stopLineTokenizationAfter:number; - stopRenderingLineAfter: number; longLineBoundary:number; forcedTokenizationBoundary:number; @@ -682,8 +827,6 @@ export interface IInternalEditorOptions { outlineMarkers: boolean; referenceInfos: boolean; folding: boolean; - renderWhitespace: boolean; - indentGuides: boolean; useTabStops: boolean; trimAutoWhitespace: boolean; @@ -692,18 +835,11 @@ export interface IInternalEditorOptions { layoutInfo: EditorLayoutInfo; fontInfo: FontInfo; - editorClassName: string; + + viewInfo: InternalEditorViewOptions; wrappingInfo: IEditorWrappingInfo; - /** - * Computed width of the container of the editor in px. - */ - observedOuterWidth:number; - /** - * Computed height of the container of the editor in px. - */ - observedOuterHeight:number; /** * Computed line height (deduced from theme and CSS) in px. */ @@ -718,34 +854,19 @@ export interface IInternalEditorOptions { * An event describing that the configuration of the editor has changed. */ export interface IConfigurationChangedEvent { - experimentalScreenReader: boolean; - rulers: boolean; wordSeparators: boolean; selectionClipboard: boolean; - ariaLabel: boolean; // ---- Options that are transparent - get no massaging - lineNumbers: boolean; - selectOnLineNumbers: boolean; - glyphMargin: boolean; - revealHorizontalRightPadding: boolean; - roundedSelection: boolean; theme: boolean; readOnly: boolean; - scrollbar: boolean; - overviewRulerLanes: boolean; - cursorBlinking: boolean; - cursorStyle: boolean; fontLigatures: boolean; - hideCursorInOverviewRuler: boolean; - scrollBeyondLastLine: boolean; wrappingIndent: boolean; wordWrapBreakBeforeCharacters: boolean; wordWrapBreakAfterCharacters: boolean; wordWrapBreakObtrusiveCharacters: boolean; tabFocusMode: boolean; stopLineTokenizationAfter: boolean; - stopRenderingLineAfter: boolean; longLineBoundary: boolean; forcedTokenizationBoundary: boolean; @@ -762,18 +883,14 @@ export interface IConfigurationChangedEvent { outlineMarkers: boolean; referenceInfos: boolean; folding: boolean; - renderWhitespace: boolean; - indentGuides: boolean; useTabStops: boolean; trimAutoWhitespace: boolean; // ---- Options that are computed layoutInfo: boolean; fontInfo: boolean; - editorClassName: boolean; + viewInfo: IViewConfigurationChangedEvent; wrappingInfo: boolean; - observedOuterWidth: boolean; - observedOuterHeight: boolean; lineHeight: boolean; pageSize: boolean; } diff --git a/src/vs/editor/common/viewLayout/linesLayout.ts b/src/vs/editor/common/viewLayout/linesLayout.ts index c8e2d194f26..f49143c0030 100644 --- a/src/vs/editor/common/viewLayout/linesLayout.ts +++ b/src/vs/editor/common/viewLayout/linesLayout.ts @@ -29,7 +29,7 @@ export class LinesLayout { constructor(configuration: editorCommon.IConfiguration, model:IViewModel) { this.configuration = configuration; this._lineHeight = this.configuration.editor.lineHeight; - this._scrollBeyondLastLine = this.configuration.editor.scrollBeyondLastLine; + this._scrollBeyondLastLine = this.configuration.editor.viewInfo.scrollBeyondLastLine; this.model = model; this.verticalObjects = new VerticalObjects(); @@ -40,8 +40,8 @@ export class LinesLayout { if (e.lineHeight) { this._lineHeight = this.configuration.editor.lineHeight; } - if (e.scrollBeyondLastLine) { - this._scrollBeyondLastLine = this.configuration.editor.scrollBeyondLastLine; + if (e.viewInfo.scrollBeyondLastLine) { + this._scrollBeyondLastLine = this.configuration.editor.viewInfo.scrollBeyondLastLine; } } diff --git a/src/vs/editor/common/viewModel/viewModelCursors.ts b/src/vs/editor/common/viewModel/viewModelCursors.ts index 3c5e66410df..c618a666827 100644 --- a/src/vs/editor/common/viewModel/viewModelCursors.ts +++ b/src/vs/editor/common/viewModel/viewModelCursors.ts @@ -47,7 +47,7 @@ export class ViewModelCursors { this.lastCursorPositionChangedEvent = e; var position = this.converter.validateViewPosition(e.viewPosition.lineNumber, e.viewPosition.column, e.position), - stopRenderingLineAfter = this.configuration.editor.stopRenderingLineAfter; + stopRenderingLineAfter = this.configuration.editor.viewInfo.stopRenderingLineAfter; // Limit position to be somewhere where it can actually be rendered if (stopRenderingLineAfter !== -1 && position.column > stopRenderingLineAfter) { diff --git a/src/vs/editor/common/viewModel/viewModelImpl.ts b/src/vs/editor/common/viewModel/viewModelImpl.ts index ee972b31d5c..d174858848d 100644 --- a/src/vs/editor/common/viewModel/viewModelImpl.ts +++ b/src/vs/editor/common/viewModel/viewModelImpl.ts @@ -419,8 +419,8 @@ export class ViewModel extends EventEmitter implements IViewModel { } var modelLineNumber = modelPosition.lineNumber; - if (typeof this.configuration.editor.lineNumbers === 'function') { - return this.configuration.editor.lineNumbers(modelLineNumber); + if (typeof this.configuration.editor.viewInfo.lineNumbers === 'function') { + return this.configuration.editor.viewInfo.lineNumbers(modelLineNumber); } return modelLineNumber.toString(); diff --git a/src/vs/editor/contrib/indentation/common/indentation.ts b/src/vs/editor/contrib/indentation/common/indentation.ts index ece45c52b08..97135e499c4 100644 --- a/src/vs/editor/contrib/indentation/common/indentation.ts +++ b/src/vs/editor/contrib/indentation/common/indentation.ts @@ -161,7 +161,7 @@ export class ToggleRenderWhitespaceAction extends EditorAction { public run(): TPromise { this.editor.updateOptions({ - renderWhitespace: !this.editor.getConfiguration().renderWhitespace + renderWhitespace: !this.editor.getConfiguration().viewInfo.renderWhitespace }); return TPromise.as(true); diff --git a/src/vs/workbench/api/node/mainThreadEditors.ts b/src/vs/workbench/api/node/mainThreadEditors.ts index 4b309ff1dee..feb3350efe8 100644 --- a/src/vs/workbench/api/node/mainThreadEditors.ts +++ b/src/vs/workbench/api/node/mainThreadEditors.ts @@ -272,7 +272,7 @@ export class MainThreadTextEditor { let cursorStyle = this._configuration ? this._configuration.cursorStyle : EditorCommon.TextEditorCursorStyle.Line; if (codeEditor) { let codeEditorOpts = codeEditor.getConfiguration(); - cursorStyle = codeEditorOpts.cursorStyle; + cursorStyle = codeEditorOpts.viewInfo.cursorStyle; } let indent = model.getOptions(); From 4399bae159af4a4532fcc27179ced29974064274 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 6 May 2016 14:16:49 +0200 Subject: [PATCH 085/297] Convert IEditorWrappingInfo to EditorWrappingInfo --- src/vs/editor/common/commonCodeEditor.ts | 8 +-- .../common/config/commonEditorConfig.ts | 54 +++++------------ src/vs/editor/common/config/defaultConfig.ts | 1 - src/vs/editor/common/editorCommon.ts | 60 +++++++++++++------ .../editor/common/viewModel/viewModelImpl.ts | 2 +- .../toggleWordWrap/common/toggleWordWrap.ts | 10 +++- .../viewModel/splitLinesCollection.test.ts | 8 +-- 7 files changed, 72 insertions(+), 71 deletions(-) diff --git a/src/vs/editor/common/commonCodeEditor.ts b/src/vs/editor/common/commonCodeEditor.ts index abfd2b1b5ff..54cc47df599 100644 --- a/src/vs/editor/common/commonCodeEditor.ts +++ b/src/vs/editor/common/commonCodeEditor.ts @@ -675,9 +675,9 @@ export abstract class CommonCodeEditor extends EventEmitter implements IActionPr this.model.onBeforeAttached(); var hardWrappingLineMapperFactory = new CharacterHardWrappingLineMapperFactory( - this._configuration.editor.wordWrapBreakBeforeCharacters, - this._configuration.editor.wordWrapBreakAfterCharacters, - this._configuration.editor.wordWrapBreakObtrusiveCharacters + this._configuration.editor.wrappingInfo.wordWrapBreakBeforeCharacters, + this._configuration.editor.wrappingInfo.wordWrapBreakAfterCharacters, + this._configuration.editor.wrappingInfo.wordWrapBreakObtrusiveCharacters ); var linesCollection = new SplitLinesCollection( @@ -686,7 +686,7 @@ export abstract class CommonCodeEditor extends EventEmitter implements IActionPr this.model.getOptions().tabSize, this._configuration.editor.wrappingInfo.wrappingColumn, this._configuration.editor.fontInfo.typicalFullwidthCharacterWidth / this._configuration.editor.fontInfo.typicalHalfwidthCharacterWidth, - this._configuration.editor.wrappingIndent + this._configuration.editor.wrappingInfo.wrappingIndent ); this.viewModel = new ViewModel( diff --git a/src/vs/editor/common/config/commonEditorConfig.ts b/src/vs/editor/common/config/commonEditorConfig.ts index fcffb4cc4cb..6da46f0b233 100644 --- a/src/vs/editor/common/config/commonEditorConfig.ts +++ b/src/vs/editor/common/config/commonEditorConfig.ts @@ -70,14 +70,9 @@ export class InternalEditorOptions implements editorCommon.IInternalEditorOption theme:string; readOnly:boolean; fontLigatures:boolean; - wrappingIndent: editorCommon.WrappingIndent; - wordWrapBreakBeforeCharacters: string; - wordWrapBreakAfterCharacters: string; - wordWrapBreakObtrusiveCharacters: string; tabFocusMode:boolean; stopLineTokenizationAfter:number; longLineBoundary:number; - forcedTokenizationBoundary:number; hover:boolean; contextmenu:boolean; quickSuggestions:boolean; @@ -96,7 +91,7 @@ export class InternalEditorOptions implements editorCommon.IInternalEditorOption layoutInfo: editorCommon.EditorLayoutInfo; fontInfo: editorCommon.FontInfo; viewInfo: editorCommon.InternalEditorViewOptions; - wrappingInfo: editorCommon.IEditorWrappingInfo; + wrappingInfo: editorCommon.EditorWrappingInfo; lineHeight:number; pageSize:number; @@ -106,14 +101,9 @@ export class InternalEditorOptions implements editorCommon.IInternalEditorOption this.theme = String(input.theme); this.readOnly = Boolean(input.readOnly); this.fontLigatures = Boolean(input.fontLigatures); - this.wrappingIndent = input.wrappingIndent; - this.wordWrapBreakBeforeCharacters = String(input.wordWrapBreakBeforeCharacters); - this.wordWrapBreakAfterCharacters = String(input.wordWrapBreakAfterCharacters); - this.wordWrapBreakObtrusiveCharacters = String(input.wordWrapBreakObtrusiveCharacters); this.tabFocusMode = Boolean(input.tabFocusMode); this.stopLineTokenizationAfter = Number(input.stopLineTokenizationAfter)|0; this.longLineBoundary = Number(input.longLineBoundary)|0; - this.forcedTokenizationBoundary = Number(input.forcedTokenizationBoundary)|0; this.hover = Boolean(input.hover); this.contextmenu = Boolean(input.contextmenu); this.quickSuggestions = Boolean(input.quickSuggestions); @@ -132,10 +122,7 @@ export class InternalEditorOptions implements editorCommon.IInternalEditorOption this.layoutInfo = input.layoutInfo.clone(); this.fontInfo = input.fontInfo.clone(); this.viewInfo = input.viewInfo.clone(); - this.wrappingInfo = { - isViewportWrapping: Boolean(input.wrappingInfo.isViewportWrapping), - wrappingColumn: Number(input.wrappingInfo.wrappingColumn)|0, - }; + this.wrappingInfo = input.wrappingInfo.clone(); this.lineHeight = Number(input.lineHeight)|0; this.pageSize = Number(input.pageSize)|0; } @@ -208,26 +195,33 @@ class InternalEditorOptionsHelper { wrappingColumn = 0; } - let wrappingInfo: editorCommon.IEditorWrappingInfo; - + let bareWrappingInfo: { isViewportWrapping: boolean; wrappingColumn: number; }; if (wrappingColumn === 0) { // If viewport width wrapping is enabled - wrappingInfo = { + bareWrappingInfo = { isViewportWrapping: true, wrappingColumn: Math.max(1, Math.floor((layoutInfo.contentWidth - layoutInfo.verticalScrollbarWidth) / fontInfo.typicalHalfwidthCharacterWidth)) }; } else if (wrappingColumn > 0) { // Wrapping is enabled - wrappingInfo = { + bareWrappingInfo = { isViewportWrapping: false, wrappingColumn: wrappingColumn }; } else { - wrappingInfo = { + bareWrappingInfo = { isViewportWrapping: false, wrappingColumn: -1 }; } + let wrappingInfo = new editorCommon.EditorWrappingInfo({ + isViewportWrapping: bareWrappingInfo.isViewportWrapping, + wrappingColumn: bareWrappingInfo.wrappingColumn, + wrappingIndent: wrappingIndentFromString(opts.wrappingIndent), + wordWrapBreakBeforeCharacters: String(opts.wordWrapBreakBeforeCharacters), + wordWrapBreakAfterCharacters: String(opts.wordWrapBreakAfterCharacters), + wordWrapBreakObtrusiveCharacters: String(opts.wordWrapBreakObtrusiveCharacters), + }); let readOnly = toBoolean(opts.readOnly); @@ -264,14 +258,9 @@ class InternalEditorOptionsHelper { wordSeparators: String(opts.wordSeparators), selectionClipboard: toBoolean(opts.selectionClipboard), fontLigatures: toBoolean(opts.fontLigatures), - wrappingIndent: wrappingIndentFromString(opts.wrappingIndent), - wordWrapBreakBeforeCharacters: opts.wordWrapBreakBeforeCharacters, - wordWrapBreakAfterCharacters: opts.wordWrapBreakAfterCharacters, - wordWrapBreakObtrusiveCharacters: opts.wordWrapBreakObtrusiveCharacters, tabFocusMode: tabFocusMode, stopLineTokenizationAfter: stopLineTokenizationAfter, longLineBoundary: toInteger(opts.longLineBoundary), - forcedTokenizationBoundary: toInteger(opts.forcedTokenizationBoundary), hover: toBoolean(opts.hover), contextmenu: toBoolean(opts.contextmenu), @@ -343,14 +332,9 @@ class InternalEditorOptionsHelper { theme: (prevOpts.theme !== newOpts.theme), readOnly: (prevOpts.readOnly !== newOpts.readOnly), fontLigatures: (prevOpts.fontLigatures !== newOpts.fontLigatures), - wrappingIndent: (prevOpts.wrappingIndent !== newOpts.wrappingIndent), - wordWrapBreakBeforeCharacters: (prevOpts.wordWrapBreakBeforeCharacters !== newOpts.wordWrapBreakBeforeCharacters), - wordWrapBreakAfterCharacters: (prevOpts.wordWrapBreakAfterCharacters !== newOpts.wordWrapBreakAfterCharacters), - wordWrapBreakObtrusiveCharacters:(prevOpts.wordWrapBreakObtrusiveCharacters !== newOpts.wordWrapBreakObtrusiveCharacters), tabFocusMode: (prevOpts.tabFocusMode !== newOpts.tabFocusMode), stopLineTokenizationAfter: (prevOpts.stopLineTokenizationAfter !== newOpts.stopLineTokenizationAfter), longLineBoundary: (prevOpts.longLineBoundary !== newOpts.longLineBoundary), - forcedTokenizationBoundary: (prevOpts.forcedTokenizationBoundary !== newOpts.forcedTokenizationBoundary), hover: (prevOpts.hover !== newOpts.hover), contextmenu: (prevOpts.contextmenu !== newOpts.contextmenu), @@ -370,19 +354,11 @@ class InternalEditorOptionsHelper { layoutInfo: (!prevOpts.layoutInfo.equals(newOpts.layoutInfo)), fontInfo: (!prevOpts.fontInfo.equals(newOpts.fontInfo)), viewInfo: prevOpts.viewInfo.createChangeEvent(newOpts.viewInfo), - wrappingInfo: (!this._wrappingInfoEqual(prevOpts.wrappingInfo, newOpts.wrappingInfo)), + wrappingInfo: (!prevOpts.wrappingInfo.equals(newOpts.wrappingInfo)), lineHeight: (prevOpts.lineHeight !== newOpts.lineHeight), pageSize: (prevOpts.pageSize !== newOpts.pageSize), }; } - - private static _wrappingInfoEqual(a:editorCommon.IEditorWrappingInfo, b:editorCommon.IEditorWrappingInfo): boolean { - return ( - a.isViewportWrapping === b.isViewportWrapping - && a.wrappingColumn === b.wrappingColumn - ); - } - } function toBoolean(value:any): boolean { diff --git a/src/vs/editor/common/config/defaultConfig.ts b/src/vs/editor/common/config/defaultConfig.ts index 462a09b0e80..a7dbd770e60 100644 --- a/src/vs/editor/common/config/defaultConfig.ts +++ b/src/vs/editor/common/config/defaultConfig.ts @@ -71,7 +71,6 @@ class ConfigClass implements IConfiguration { // stopLineTokenizationAfter // stopRenderingLineAfter longLineBoundary: 300, - forcedTokenizationBoundary: 1000, // Features hover: true, diff --git a/src/vs/editor/common/editorCommon.ts b/src/vs/editor/common/editorCommon.ts index b396e507b32..9b0831d9bd7 100644 --- a/src/vs/editor/common/editorCommon.ts +++ b/src/vs/editor/common/editorCommon.ts @@ -427,13 +427,6 @@ export interface IEditorOptions { * Defaults to 300. */ longLineBoundary?:number; - /** - * Performance guard: Tokenize in the background if the [wrapped] lines count is above - * this number. If the [wrapped] lines count is below this number, then the view will - * always force tokenization before rendering. - * Defaults to 1000. - */ - forcedTokenizationBoundary?:number; /** * Enable hover. * Defaults to true. @@ -628,12 +621,51 @@ export class InternalEditorScrollbarOptions { } } -export interface IEditorWrappingInfo { +export class EditorWrappingInfo { + _editorWrappingInfoBrand: void; + isViewportWrapping: boolean; wrappingColumn: number; + wrappingIndent: WrappingIndent; + wordWrapBreakBeforeCharacters: string; + wordWrapBreakAfterCharacters: string; + wordWrapBreakObtrusiveCharacters: string; + + constructor(source:{ + isViewportWrapping: boolean; + wrappingColumn: number; + wrappingIndent: WrappingIndent; + wordWrapBreakBeforeCharacters: string; + wordWrapBreakAfterCharacters: string; + wordWrapBreakObtrusiveCharacters: string; + }) { + this.isViewportWrapping = Boolean(source.isViewportWrapping); + this.wrappingColumn = source.wrappingColumn|0; + this.wrappingIndent = source.wrappingIndent|0; + this.wordWrapBreakBeforeCharacters = String(source.wordWrapBreakBeforeCharacters); + this.wordWrapBreakAfterCharacters = String(source.wordWrapBreakAfterCharacters); + this.wordWrapBreakObtrusiveCharacters = String(source.wordWrapBreakObtrusiveCharacters); + } + + public equals(other:EditorWrappingInfo): boolean { + return ( + this.isViewportWrapping === other.isViewportWrapping + && this.wrappingColumn === other.wrappingColumn + && this.wrappingIndent === other.wrappingIndent + && this.wordWrapBreakBeforeCharacters === other.wordWrapBreakBeforeCharacters + && this.wordWrapBreakAfterCharacters === other.wordWrapBreakAfterCharacters + && this.wordWrapBreakObtrusiveCharacters === other.wordWrapBreakObtrusiveCharacters + ); + } + + public clone(): EditorWrappingInfo { + return new EditorWrappingInfo(this); + } } export class InternalEditorViewOptions { + _internalEditorViewOptionsBrand: void; + experimentalScreenReader: boolean; rulers: number[]; ariaLabel: string; @@ -804,14 +836,9 @@ export interface IInternalEditorOptions { theme:string; readOnly:boolean; fontLigatures:boolean; - wrappingIndent: WrappingIndent; - wordWrapBreakBeforeCharacters: string; - wordWrapBreakAfterCharacters: string; - wordWrapBreakObtrusiveCharacters: string; tabFocusMode:boolean; stopLineTokenizationAfter:number; longLineBoundary:number; - forcedTokenizationBoundary:number; // ---- Options that are transparent - get no massaging hover:boolean; @@ -838,7 +865,7 @@ export interface IInternalEditorOptions { viewInfo: InternalEditorViewOptions; - wrappingInfo: IEditorWrappingInfo; + wrappingInfo: EditorWrappingInfo; /** * Computed line height (deduced from theme and CSS) in px. @@ -861,14 +888,9 @@ export interface IConfigurationChangedEvent { theme: boolean; readOnly: boolean; fontLigatures: boolean; - wrappingIndent: boolean; - wordWrapBreakBeforeCharacters: boolean; - wordWrapBreakAfterCharacters: boolean; - wordWrapBreakObtrusiveCharacters: boolean; tabFocusMode: boolean; stopLineTokenizationAfter: boolean; longLineBoundary: boolean; - forcedTokenizationBoundary: boolean; // ---- Options that are transparent - get no massaging hover: boolean; diff --git a/src/vs/editor/common/viewModel/viewModelImpl.ts b/src/vs/editor/common/viewModel/viewModelImpl.ts index d174858848d..e9bae0dc8b6 100644 --- a/src/vs/editor/common/viewModel/viewModelImpl.ts +++ b/src/vs/editor/common/viewModel/viewModelImpl.ts @@ -259,7 +259,7 @@ export class ViewModel extends EventEmitter implements IViewModel { break; case editorCommon.EventType.ConfigurationChanged: - revealPreviousCenteredModelRange = this._onWrappingIndentChange(this.configuration.editor.wrappingIndent) || revealPreviousCenteredModelRange; + revealPreviousCenteredModelRange = this._onWrappingIndentChange(this.configuration.editor.wrappingInfo.wrappingIndent) || revealPreviousCenteredModelRange; revealPreviousCenteredModelRange = this._onWrappingColumnChange(this.configuration.editor.wrappingInfo.wrappingColumn, this.configuration.editor.fontInfo.typicalFullwidthCharacterWidth / this.configuration.editor.fontInfo.typicalHalfwidthCharacterWidth) || revealPreviousCenteredModelRange; if ((data).readOnly) { // Must read again all decorations due to readOnly filtering diff --git a/src/vs/editor/contrib/toggleWordWrap/common/toggleWordWrap.ts b/src/vs/editor/contrib/toggleWordWrap/common/toggleWordWrap.ts index f9884f27123..626945be251 100644 --- a/src/vs/editor/contrib/toggleWordWrap/common/toggleWordWrap.ts +++ b/src/vs/editor/contrib/toggleWordWrap/common/toggleWordWrap.ts @@ -24,12 +24,16 @@ class ToggleWordWrapAction extends EditorAction { let wrappingInfo = this.editor.getConfiguration().wrappingInfo; + let newWrappingColumn: number; if (!wrappingInfo.isViewportWrapping) { - wrappingInfo.wrappingColumn = 0; + newWrappingColumn = 0; } else { - wrappingInfo.wrappingColumn = -1; + newWrappingColumn = -1; } - this.editor.updateOptions(wrappingInfo); + + this.editor.updateOptions({ + wrappingColumn: newWrappingColumn + }); return TPromise.as(true); } diff --git a/src/vs/editor/test/common/viewModel/splitLinesCollection.test.ts b/src/vs/editor/test/common/viewModel/splitLinesCollection.test.ts index 0aad2fb2302..448e420670c 100644 --- a/src/vs/editor/test/common/viewModel/splitLinesCollection.test.ts +++ b/src/vs/editor/test/common/viewModel/splitLinesCollection.test.ts @@ -84,9 +84,9 @@ suite('Editor ViewModel - SplitLinesCollection', () => { let config = new MockConfiguration({}); let hardWrappingLineMapperFactory = new CharacterHardWrappingLineMapperFactory( - config.editor.wordWrapBreakBeforeCharacters, - config.editor.wordWrapBreakAfterCharacters, - config.editor.wordWrapBreakObtrusiveCharacters + config.editor.wrappingInfo.wordWrapBreakBeforeCharacters, + config.editor.wrappingInfo.wordWrapBreakAfterCharacters, + config.editor.wrappingInfo.wordWrapBreakObtrusiveCharacters ); let model = new Model([ @@ -104,7 +104,7 @@ suite('Editor ViewModel - SplitLinesCollection', () => { model.getOptions().tabSize, config.editor.wrappingInfo.wrappingColumn, config.editor.fontInfo.typicalFullwidthCharacterWidth / config.editor.fontInfo.typicalHalfwidthCharacterWidth, - config.editor.wrappingIndent + config.editor.wrappingInfo.wrappingIndent ); linesCollection.setHiddenAreas([{ From fe9bc04a75e92c4630cd1917320b8d8827e4548b Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 6 May 2016 14:31:41 +0200 Subject: [PATCH 086/297] debug: respect showUser flag in errors fixes #5828 --- src/vs/workbench/parts/debug/node/rawDebugSession.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/vs/workbench/parts/debug/node/rawDebugSession.ts b/src/vs/workbench/parts/debug/node/rawDebugSession.ts index 3032ca03445..d792314962b 100644 --- a/src/vs/workbench/parts/debug/node/rawDebugSession.ts +++ b/src/vs/workbench/parts/debug/node/rawDebugSession.ts @@ -148,6 +148,9 @@ export class RawDebugSession extends v8.V8Protocol implements debug.IRawDebugSes this.telemetryService.publicLog('debugProtocolErrorResponse', { error: message }); this.telemtryAdapter.log('debugProtocolErrorResponse', { error: message }); } + if (error && error.showUser === false) { + return TPromise.as(null); + } if (error && error.url) { const label = error.urlLabel ? error.urlLabel : nls.localize('moreInfo', "More Info"); From e477f92ee01c34deaceb4f87ea13a102f931edd2 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 6 May 2016 14:41:31 +0200 Subject: [PATCH 087/297] Group editor contrib options --- .../common/config/commonEditorConfig.ts | 67 +++-------- src/vs/editor/common/editorCommon.ts | 113 ++++++++++++------ .../contrib/codelens/browser/codelens.ts | 8 +- .../contextmenu/browser/contextmenu.ts | 6 +- .../contrib/find/common/findController.ts | 2 +- .../editor/contrib/folding/browser/folding.ts | 10 +- .../contrib/format/common/formatActions.ts | 2 +- src/vs/editor/contrib/hover/browser/hover.ts | 4 +- .../outlineMarker/browser/outlineMarker.ts | 8 +- .../contrib/quickFix/browser/quickFixModel.ts | 2 +- .../electron-browser/selectionClipboard.ts | 6 +- .../editor/contrib/suggest/browser/suggest.ts | 2 +- .../contrib/suggest/browser/suggestModel.ts | 4 +- .../contrib/suggest/browser/suggestWidget.ts | 2 +- 14 files changed, 129 insertions(+), 107 deletions(-) diff --git a/src/vs/editor/common/config/commonEditorConfig.ts b/src/vs/editor/common/config/commonEditorConfig.ts index 6da46f0b233..903165d19a8 100644 --- a/src/vs/editor/common/config/commonEditorConfig.ts +++ b/src/vs/editor/common/config/commonEditorConfig.ts @@ -66,63 +66,39 @@ export class InternalEditorOptions implements editorCommon.IInternalEditorOption _internalEditorOptionsBrand: void; wordSeparators: string; - selectionClipboard: boolean; theme:string; readOnly:boolean; fontLigatures:boolean; tabFocusMode:boolean; stopLineTokenizationAfter:number; longLineBoundary:number; - hover:boolean; - contextmenu:boolean; - quickSuggestions:boolean; - quickSuggestionsDelay:number; - iconsInSuggestions:boolean; autoClosingBrackets:boolean; - formatOnType:boolean; - suggestOnTriggerCharacters: boolean; - acceptSuggestionOnEnter: boolean; - selectionHighlight:boolean; - outlineMarkers: boolean; - referenceInfos: boolean; - folding: boolean; useTabStops: boolean; trimAutoWhitespace: boolean; layoutInfo: editorCommon.EditorLayoutInfo; fontInfo: editorCommon.FontInfo; viewInfo: editorCommon.InternalEditorViewOptions; wrappingInfo: editorCommon.EditorWrappingInfo; + contribInfo: editorCommon.EditorContribOptions; lineHeight:number; pageSize:number; constructor(input:editorCommon.IInternalEditorOptions) { this.wordSeparators = String(input.wordSeparators); - this.selectionClipboard = Boolean(input.selectionClipboard); this.theme = String(input.theme); this.readOnly = Boolean(input.readOnly); this.fontLigatures = Boolean(input.fontLigatures); this.tabFocusMode = Boolean(input.tabFocusMode); this.stopLineTokenizationAfter = Number(input.stopLineTokenizationAfter)|0; this.longLineBoundary = Number(input.longLineBoundary)|0; - this.hover = Boolean(input.hover); - this.contextmenu = Boolean(input.contextmenu); - this.quickSuggestions = Boolean(input.quickSuggestions); - this.quickSuggestionsDelay = Number(input.quickSuggestionsDelay)|0; - this.iconsInSuggestions = Boolean(input.iconsInSuggestions); this.autoClosingBrackets = Boolean(input.autoClosingBrackets); - this.formatOnType = Boolean(input.formatOnType); - this.suggestOnTriggerCharacters = Boolean(input.suggestOnTriggerCharacters); - this.acceptSuggestionOnEnter = Boolean(input.acceptSuggestionOnEnter); - this.selectionHighlight = Boolean(input.selectionHighlight); - this.outlineMarkers = Boolean(input.outlineMarkers); - this.referenceInfos = Boolean(input.referenceInfos); - this.folding = Boolean(input.folding); this.useTabStops = Boolean(input.useTabStops); this.trimAutoWhitespace = Boolean(input.trimAutoWhitespace); this.layoutInfo = input.layoutInfo.clone(); this.fontInfo = input.fontInfo.clone(); this.viewInfo = input.viewInfo.clone(); this.wrappingInfo = input.wrappingInfo.clone(); + this.contribInfo = input.contribInfo.clone(); this.lineHeight = Number(input.lineHeight)|0; this.pageSize = Number(input.pageSize)|0; } @@ -251,23 +227,13 @@ class InternalEditorOptionsHelper { scrollbar: scrollbar, }); - return { - // ---- Options that are transparent - get no massaging - theme: opts.theme, - readOnly: readOnly, - wordSeparators: String(opts.wordSeparators), + let contribInfo = new editorCommon.EditorContribOptions({ selectionClipboard: toBoolean(opts.selectionClipboard), - fontLigatures: toBoolean(opts.fontLigatures), - tabFocusMode: tabFocusMode, - stopLineTokenizationAfter: stopLineTokenizationAfter, - longLineBoundary: toInteger(opts.longLineBoundary), - hover: toBoolean(opts.hover), contextmenu: toBoolean(opts.contextmenu), quickSuggestions: toBoolean(opts.quickSuggestions), quickSuggestionsDelay: toInteger(opts.quickSuggestionsDelay), iconsInSuggestions: toBoolean(opts.iconsInSuggestions), - autoClosingBrackets: toBoolean(opts.autoClosingBrackets), formatOnType: toBoolean(opts.formatOnType), suggestOnTriggerCharacters: toBoolean(opts.suggestOnTriggerCharacters), acceptSuggestionOnEnter: toBoolean(opts.acceptSuggestionOnEnter), @@ -275,6 +241,19 @@ class InternalEditorOptionsHelper { outlineMarkers: toBoolean(opts.outlineMarkers), referenceInfos: toBoolean(opts.referenceInfos), folding: toBoolean(opts.folding), + }); + + return { + // ---- Options that are transparent - get no massaging + theme: opts.theme, + readOnly: readOnly, + wordSeparators: String(opts.wordSeparators), + fontLigatures: toBoolean(opts.fontLigatures), + tabFocusMode: tabFocusMode, + stopLineTokenizationAfter: stopLineTokenizationAfter, + longLineBoundary: toInteger(opts.longLineBoundary), + + autoClosingBrackets: toBoolean(opts.autoClosingBrackets), useTabStops: toBoolean(opts.useTabStops), trimAutoWhitespace: toBoolean(opts.trimAutoWhitespace), @@ -282,6 +261,7 @@ class InternalEditorOptionsHelper { fontInfo: fontInfo, viewInfo: viewInfo, wrappingInfo: wrappingInfo, + contribInfo: contribInfo, lineHeight: fontInfo.lineHeight, // todo -> duplicated in styling pageSize: pageSize, @@ -327,7 +307,6 @@ class InternalEditorOptionsHelper { public static createConfigurationChangedEvent(prevOpts:InternalEditorOptions, newOpts:InternalEditorOptions): editorCommon.IConfigurationChangedEvent { return { wordSeparators: (prevOpts.wordSeparators !== newOpts.wordSeparators), - selectionClipboard: (prevOpts.selectionClipboard !== newOpts.selectionClipboard), theme: (prevOpts.theme !== newOpts.theme), readOnly: (prevOpts.readOnly !== newOpts.readOnly), @@ -336,18 +315,7 @@ class InternalEditorOptionsHelper { stopLineTokenizationAfter: (prevOpts.stopLineTokenizationAfter !== newOpts.stopLineTokenizationAfter), longLineBoundary: (prevOpts.longLineBoundary !== newOpts.longLineBoundary), - hover: (prevOpts.hover !== newOpts.hover), - contextmenu: (prevOpts.contextmenu !== newOpts.contextmenu), - quickSuggestions: (prevOpts.quickSuggestions !== newOpts.quickSuggestions), - quickSuggestionsDelay: (prevOpts.quickSuggestionsDelay !== newOpts.quickSuggestionsDelay), - iconsInSuggestions: (prevOpts.iconsInSuggestions !== newOpts.iconsInSuggestions), autoClosingBrackets: (prevOpts.autoClosingBrackets !== newOpts.autoClosingBrackets), - formatOnType: (prevOpts.formatOnType !== newOpts.formatOnType), - suggestOnTriggerCharacters: (prevOpts.suggestOnTriggerCharacters !== newOpts.suggestOnTriggerCharacters), - selectionHighlight: (prevOpts.selectionHighlight !== newOpts.selectionHighlight), - outlineMarkers: (prevOpts.outlineMarkers !== newOpts.outlineMarkers), - referenceInfos: (prevOpts.referenceInfos !== newOpts.referenceInfos), - folding: (prevOpts.folding !== newOpts.folding), useTabStops: (prevOpts.useTabStops !== newOpts.useTabStops), trimAutoWhitespace: (prevOpts.trimAutoWhitespace !== newOpts.trimAutoWhitespace), @@ -355,6 +323,7 @@ class InternalEditorOptionsHelper { fontInfo: (!prevOpts.fontInfo.equals(newOpts.fontInfo)), viewInfo: prevOpts.viewInfo.createChangeEvent(newOpts.viewInfo), wrappingInfo: (!prevOpts.wrappingInfo.equals(newOpts.wrappingInfo)), + contribInfo: (!prevOpts.contribInfo.equals(newOpts.contribInfo)), lineHeight: (prevOpts.lineHeight !== newOpts.lineHeight), pageSize: (prevOpts.pageSize !== newOpts.pageSize), }; diff --git a/src/vs/editor/common/editorCommon.ts b/src/vs/editor/common/editorCommon.ts index 9b0831d9bd7..8a5904b09b4 100644 --- a/src/vs/editor/common/editorCommon.ts +++ b/src/vs/editor/common/editorCommon.ts @@ -825,28 +825,13 @@ export interface IViewConfigurationChangedEvent { scrollbar: boolean; } -/** - * Internal configuration options (transformed or computed) for the editor. - */ -export interface IInternalEditorOptions { - wordSeparators: string; +export class EditorContribOptions { selectionClipboard: boolean; - - // ---- Options that are transparent - get no massaging - theme:string; - readOnly:boolean; - fontLigatures:boolean; - tabFocusMode:boolean; - stopLineTokenizationAfter:number; - longLineBoundary:number; - - // ---- Options that are transparent - get no massaging hover:boolean; contextmenu:boolean; quickSuggestions:boolean; quickSuggestionsDelay:number; iconsInSuggestions:boolean; - autoClosingBrackets:boolean; formatOnType:boolean; suggestOnTriggerCharacters: boolean; acceptSuggestionOnEnter: boolean; @@ -854,27 +839,94 @@ export interface IInternalEditorOptions { outlineMarkers: boolean; referenceInfos: boolean; folding: boolean; + + constructor(source:{ + selectionClipboard: boolean; + hover:boolean; + contextmenu:boolean; + quickSuggestions:boolean; + quickSuggestionsDelay:number; + iconsInSuggestions:boolean; + formatOnType:boolean; + suggestOnTriggerCharacters: boolean; + acceptSuggestionOnEnter: boolean; + selectionHighlight:boolean; + outlineMarkers: boolean; + referenceInfos: boolean; + folding: boolean; + }) { + this.selectionClipboard = Boolean(source.selectionClipboard); + this.hover = Boolean(source.hover); + this.contextmenu = Boolean(source.contextmenu); + this.quickSuggestions = Boolean(source.quickSuggestions); + this.quickSuggestionsDelay = source.quickSuggestionsDelay|0; + this.iconsInSuggestions = Boolean(source.iconsInSuggestions); + this.formatOnType = Boolean(source.formatOnType); + this.suggestOnTriggerCharacters = Boolean(source.suggestOnTriggerCharacters); + this.acceptSuggestionOnEnter = Boolean(source.acceptSuggestionOnEnter); + this.selectionHighlight = Boolean(source.selectionHighlight); + this.outlineMarkers = Boolean(source.outlineMarkers); + this.referenceInfos = Boolean(source.referenceInfos); + this.folding = Boolean(source.folding); + } + + public equals(other: EditorContribOptions): boolean { + return ( + this.selectionClipboard === other.selectionClipboard + && this.hover === other.hover + && this.contextmenu === other.contextmenu + && this.quickSuggestions === other.quickSuggestions + && this.quickSuggestionsDelay === other.quickSuggestionsDelay + && this.iconsInSuggestions === other.iconsInSuggestions + && this.formatOnType === other.formatOnType + && this.suggestOnTriggerCharacters === other.suggestOnTriggerCharacters + && this.acceptSuggestionOnEnter === other.acceptSuggestionOnEnter + && this.selectionHighlight === other.selectionHighlight + && this.outlineMarkers === other.outlineMarkers + && this.referenceInfos === other.referenceInfos + && this.folding === other.folding + ); + } + + public clone(): EditorContribOptions { + return new EditorContribOptions(this); + } +} + +/** + * Internal configuration options (transformed or computed) for the editor. + */ +export interface IInternalEditorOptions { + readOnly:boolean; + + // ---- cursor options + wordSeparators: string; + autoClosingBrackets:boolean; useTabStops: boolean; + pageSize:number; + tabFocusMode:boolean; + + // ---- model options trimAutoWhitespace: boolean; + stopLineTokenizationAfter:number; + longLineBoundary:number; + + // ---- Options that are transparent - get no massaging + theme:string; // todo: move to viewInfo + fontLigatures:boolean; // todo: move to fontInfo // ---- Options that are computed layoutInfo: EditorLayoutInfo; - fontInfo: FontInfo; - viewInfo: InternalEditorViewOptions; - wrappingInfo: EditorWrappingInfo; + contribInfo: EditorContribOptions; /** * Computed line height (deduced from theme and CSS) in px. */ - lineHeight:number; - /** - * Computed page size (deduced from editor size) in lines. - */ - pageSize:number; + lineHeight:number; // todo: move to fontInfo } /** @@ -882,7 +934,6 @@ export interface IInternalEditorOptions { */ export interface IConfigurationChangedEvent { wordSeparators: boolean; - selectionClipboard: boolean; // ---- Options that are transparent - get no massaging theme: boolean; @@ -893,18 +944,7 @@ export interface IConfigurationChangedEvent { longLineBoundary: boolean; // ---- Options that are transparent - get no massaging - hover: boolean; - contextmenu: boolean; - quickSuggestions: boolean; - quickSuggestionsDelay: boolean; - iconsInSuggestions: boolean; autoClosingBrackets: boolean; - formatOnType: boolean; - suggestOnTriggerCharacters: boolean; - selectionHighlight: boolean; - outlineMarkers: boolean; - referenceInfos: boolean; - folding: boolean; useTabStops: boolean; trimAutoWhitespace: boolean; @@ -913,6 +953,7 @@ export interface IConfigurationChangedEvent { fontInfo: boolean; viewInfo: IViewConfigurationChangedEvent; wrappingInfo: boolean; + contribInfo: boolean; lineHeight: boolean; pageSize: boolean; } diff --git a/src/vs/editor/contrib/codelens/browser/codelens.ts b/src/vs/editor/contrib/codelens/browser/codelens.ts index ee02aedbda1..ee4f98592e3 100644 --- a/src/vs/editor/contrib/codelens/browser/codelens.ts +++ b/src/vs/editor/contrib/codelens/browser/codelens.ts @@ -345,6 +345,7 @@ export class CodeLensContribution implements editorCommon.IEditorContribution { private _instanceCount: number; private _editor: editorBrowser.ICodeEditor; private _modelService: IModelService; + private _isEnabled: boolean; private _globalToDispose: IDisposable[]; @@ -367,6 +368,7 @@ export class CodeLensContribution implements editorCommon.IEditorContribution { this._instanceCount = (++CodeLensContribution.INSTANCE_COUNT); this._editor = editor; this._modelService = modelService; + this._isEnabled = this._editor.getConfiguration().contribInfo.referenceInfos; this._configurationService = configurationService; this._keybindingService = keybindingService; this._messageService = messageService; @@ -386,7 +388,9 @@ export class CodeLensContribution implements editorCommon.IEditorContribution { } })); this._globalToDispose.push(this._editor.addListener2(editorCommon.EventType.ConfigurationChanged, (e: editorCommon.IConfigurationChangedEvent) => { - if (e.referenceInfos) { + let prevIsEnabled = this._isEnabled; + this._isEnabled = this._editor.getConfiguration().contribInfo.referenceInfos; + if (prevIsEnabled !== this._isEnabled) { this.onModelChange(); } })); @@ -425,7 +429,7 @@ export class CodeLensContribution implements editorCommon.IEditorContribution { return; } - if (!this._editor.getConfiguration().referenceInfos) { + if (!this._isEnabled) { return; } diff --git a/src/vs/editor/contrib/contextmenu/browser/contextmenu.ts b/src/vs/editor/contrib/contextmenu/browser/contextmenu.ts index 77730093a8b..01b8bc3392e 100644 --- a/src/vs/editor/contrib/contextmenu/browser/contextmenu.ts +++ b/src/vs/editor/contrib/contextmenu/browser/contextmenu.ts @@ -61,7 +61,7 @@ class ContextMenuController implements IEditorContribution { } private _onContextMenu(e:IEditorMouseEvent): void { - if (!this._editor.getConfiguration().contextmenu) { + if (!this._editor.getConfiguration().contribInfo.contextmenu) { this._editor.focus(); // Ensure the cursor is at the position of the mouse click if (e.target.position && !this._editor.getSelection().containsPosition(e.target.position)) { @@ -99,7 +99,7 @@ class ContextMenuController implements IEditorContribution { } public showContextMenu(forcedPosition?:IPosition): void { - if (!this._editor.getConfiguration().contextmenu) { + if (!this._editor.getConfiguration().contribInfo.contextmenu) { return; // Context menu is turned off through configuration } @@ -173,7 +173,7 @@ class ContextMenuController implements IEditorContribution { this._editor.beginForcedWidgetFocus(); // Disable hover - var oldHoverSetting = this._editor.getConfiguration().hover; + var oldHoverSetting = this._editor.getConfiguration().contribInfo.hover; this._editor.updateOptions({ hover: false }); diff --git a/src/vs/editor/contrib/find/common/findController.ts b/src/vs/editor/contrib/find/common/findController.ts index 8217c1f4fbe..d424ed30394 100644 --- a/src/vs/editor/contrib/find/common/findController.ts +++ b/src/vs/editor/contrib/find/common/findController.ts @@ -565,7 +565,7 @@ export class SelectionHighlighter extends Disposable implements editorCommon.IEd } this.lastWordUnderCursor = null; - if (!this.editor.getConfiguration().selectionHighlight) { + if (!this.editor.getConfiguration().contribInfo.selectionHighlight) { return; } diff --git a/src/vs/editor/contrib/folding/browser/folding.ts b/src/vs/editor/contrib/folding/browser/folding.ts index 38f2590acc9..6e84142c162 100644 --- a/src/vs/editor/contrib/folding/browser/folding.ts +++ b/src/vs/editor/contrib/folding/browser/folding.ts @@ -140,6 +140,7 @@ export class FoldingController implements editorCommon.IEditorContribution { } private editor: ICodeEditor; + private _isEnabled: boolean; private globalToDispose: IDisposable[]; private computeToken: number; @@ -151,6 +152,7 @@ export class FoldingController implements editorCommon.IEditorContribution { constructor(editor:ICodeEditor) { this.editor = editor; + this._isEnabled = this.editor.getConfiguration().contribInfo.folding; this.globalToDispose = []; this.localToDispose = []; @@ -159,7 +161,9 @@ export class FoldingController implements editorCommon.IEditorContribution { this.globalToDispose.push(this.editor.addListener2(editorCommon.EventType.ModelChanged, () => this.onModelChanged())); this.globalToDispose.push(this.editor.addListener2(editorCommon.EventType.ConfigurationChanged, (e: editorCommon.IConfigurationChangedEvent) => { - if (e.folding) { + let oldIsEnabled = this._isEnabled; + this._isEnabled = this.editor.getConfiguration().contribInfo.folding; + if (oldIsEnabled !== this._isEnabled) { this.onModelChanged(); } })); @@ -204,7 +208,7 @@ export class FoldingController implements editorCommon.IEditorContribution { if (!model) { return; } - if (!this.editor.getConfiguration().folding) { + if (!this._isEnabled) { return; } if (!state || !Array.isArray(state.collapsedRegions) || state.collapsedRegions.length === 0 || state.lineCount !== model.getLineCount()) { @@ -287,7 +291,7 @@ export class FoldingController implements editorCommon.IEditorContribution { this.cleanState(); let model = this.editor.getModel(); - if (!this.editor.getConfiguration().folding || !model) { + if (!this._isEnabled || !model) { return; } diff --git a/src/vs/editor/contrib/format/common/formatActions.ts b/src/vs/editor/contrib/format/common/formatActions.ts index 4352bbfff42..99b46169a76 100644 --- a/src/vs/editor/contrib/format/common/formatActions.ts +++ b/src/vs/editor/contrib/format/common/formatActions.ts @@ -53,7 +53,7 @@ class FormatOnType implements editorCommon.IEditorContribution { this.callOnModel = cAll(this.callOnModel); // we are disabled - if (!this.editor.getConfiguration().formatOnType) { + if (!this.editor.getConfiguration().contribInfo.formatOnType) { return; } diff --git a/src/vs/editor/contrib/hover/browser/hover.ts b/src/vs/editor/contrib/hover/browser/hover.ts index 98ee07f46ce..bb55f292fab 100644 --- a/src/vs/editor/contrib/hover/browser/hover.ts +++ b/src/vs/editor/contrib/hover/browser/hover.ts @@ -45,7 +45,7 @@ class ModesHoverController implements editorCommon.IEditorContribution { this._toUnhook = []; - if (editor.getConfiguration().hover) { + if (editor.getConfiguration().contribInfo.hover) { this._toUnhook.push(this._editor.addListener(editorCommon.EventType.MouseDown, (e: IEditorMouseEvent) => this._onEditorMouseDown(e))); this._toUnhook.push(this._editor.addListener(editorCommon.EventType.MouseMove, (e: IEditorMouseEvent) => this._onEditorMouseMove(e))); this._toUnhook.push(this._editor.addListener(editorCommon.EventType.MouseLeave, (e: IEditorMouseEvent) => this._hideWidgets())); @@ -94,7 +94,7 @@ class ModesHoverController implements editorCommon.IEditorContribution { return; } - if (this._editor.getConfiguration().hover && targetType === editorCommon.MouseTargetType.CONTENT_TEXT) { + if (this._editor.getConfiguration().contribInfo.hover && targetType === editorCommon.MouseTargetType.CONTENT_TEXT) { this._glyphWidget.hide(); this._contentWidget.startShowingAt(mouseEvent.target.range, false); } else if (targetType === editorCommon.MouseTargetType.GUTTER_GLYPH_MARGIN) { diff --git a/src/vs/editor/contrib/outlineMarker/browser/outlineMarker.ts b/src/vs/editor/contrib/outlineMarker/browser/outlineMarker.ts index 4808c56febd..d7c1c926633 100644 --- a/src/vs/editor/contrib/outlineMarker/browser/outlineMarker.ts +++ b/src/vs/editor/contrib/outlineMarker/browser/outlineMarker.ts @@ -112,6 +112,7 @@ export class OutlineMarkerContribution implements editorCommon.IEditorContributi public static ID = 'editor.outlineMarker'; private _editor:ICodeEditor; + private _isEnabled: boolean; private _globalToDispose:IDisposable[]; @@ -122,6 +123,7 @@ export class OutlineMarkerContribution implements editorCommon.IEditorContributi constructor(editor:ICodeEditor) { this._editor = editor; + this._isEnabled = this._editor.getConfiguration().contribInfo.outlineMarkers; this._globalToDispose = []; this._localToDispose = []; @@ -136,7 +138,9 @@ export class OutlineMarkerContribution implements editorCommon.IEditorContributi } })); this._globalToDispose.push(this._editor.addListener2(editorCommon.EventType.ConfigurationChanged,(e: editorCommon.IConfigurationChangedEvent) => { - if (e.outlineMarkers) { + let oldIsEnabled = this._isEnabled; + this._isEnabled = this._editor.getConfiguration().contribInfo.outlineMarkers; + if (oldIsEnabled !== this._isEnabled) { this.onChange(false); } })); @@ -168,7 +172,7 @@ export class OutlineMarkerContribution implements editorCommon.IEditorContributi this.localDispose(); - if (!this._editor.getConfiguration().outlineMarkers) { + if (!this._isEnabled) { return; } diff --git a/src/vs/editor/contrib/quickFix/browser/quickFixModel.ts b/src/vs/editor/contrib/quickFix/browser/quickFixModel.ts index 3373b4f23f5..23edf07444b 100644 --- a/src/vs/editor/contrib/quickFix/browser/quickFixModel.ts +++ b/src/vs/editor/contrib/quickFix/browser/quickFixModel.ts @@ -73,7 +73,7 @@ export class QuickFixModel extends EventEmitter { this.lightBulp = new LightBulpWidget(editor, (pos) => { this.onLightBulpClicked(pos); }); this.enableAutoQuckFix = false; // turn off for now - this.autoSuggestDelay = this.editor.getConfiguration().quickSuggestionsDelay; + this.autoSuggestDelay = this.editor.getConfiguration().contribInfo.quickSuggestionsDelay; if (isNaN(this.autoSuggestDelay) || (!this.autoSuggestDelay && this.autoSuggestDelay !== 0) || this.autoSuggestDelay > 2000 || this.autoSuggestDelay < 0) { this.autoSuggestDelay = 300; } diff --git a/src/vs/editor/contrib/selectionClipboard/electron-browser/selectionClipboard.ts b/src/vs/editor/contrib/selectionClipboard/electron-browser/selectionClipboard.ts index a4d6c3d6d22..72fe4eaa3e9 100644 --- a/src/vs/editor/contrib/selectionClipboard/electron-browser/selectionClipboard.ts +++ b/src/vs/editor/contrib/selectionClipboard/electron-browser/selectionClipboard.ts @@ -23,11 +23,11 @@ class SelectionClipboard extends Disposable implements IEditorContribution { super(); if (platform.isLinux) { - var isEnabled = editor.getConfiguration().selectionClipboard; + var isEnabled = editor.getConfiguration().contribInfo.selectionClipboard; this._register(editor.addListener2(EventType.ConfigurationChanged, (e:IConfigurationChangedEvent) => { - if (e.selectionClipboard) { - isEnabled = editor.getConfiguration().selectionClipboard; + if (e.contribInfo) { + isEnabled = editor.getConfiguration().contribInfo.selectionClipboard; } })); diff --git a/src/vs/editor/contrib/suggest/browser/suggest.ts b/src/vs/editor/contrib/suggest/browser/suggest.ts index fe1e557de20..d97e30dd0eb 100644 --- a/src/vs/editor/contrib/suggest/browser/suggest.ts +++ b/src/vs/editor/contrib/suggest/browser/suggest.ts @@ -89,7 +89,7 @@ export class SuggestController implements IEditorContribution { if (this.editor.getConfiguration().readOnly || !this.editor.getModel() - || !this.editor.getConfiguration().suggestOnTriggerCharacters) { + || !this.editor.getConfiguration().contribInfo.suggestOnTriggerCharacters) { return; } diff --git a/src/vs/editor/contrib/suggest/browser/suggestModel.ts b/src/vs/editor/contrib/suggest/browser/suggestModel.ts index c2add8694a7..c99c810fa4c 100644 --- a/src/vs/editor/contrib/suggest/browser/suggestModel.ts +++ b/src/vs/editor/contrib/suggest/browser/suggestModel.ts @@ -262,7 +262,7 @@ export class SuggestModel implements IDisposable { const isInactive = this.state === State.Idle; - if (isInactive && !this.editor.getConfiguration().quickSuggestions) { + if (isInactive && !this.editor.getConfiguration().contribInfo.quickSuggestions) { return; } @@ -396,7 +396,7 @@ export class SuggestModel implements IDisposable { } private onEditorConfigurationChange(): void { - this.autoSuggestDelay = this.editor.getConfiguration().quickSuggestionsDelay; + this.autoSuggestDelay = this.editor.getConfiguration().contribInfo.quickSuggestionsDelay; if (isNaN(this.autoSuggestDelay) || (!this.autoSuggestDelay && this.autoSuggestDelay !== 0) || this.autoSuggestDelay < 0) { this.autoSuggestDelay = 10; diff --git a/src/vs/editor/contrib/suggest/browser/suggestWidget.ts b/src/vs/editor/contrib/suggest/browser/suggestWidget.ts index eab66e6a63d..31cc70d09e5 100644 --- a/src/vs/editor/contrib/suggest/browser/suggestWidget.ts +++ b/src/vs/editor/contrib/suggest/browser/suggestWidget.ts @@ -355,7 +355,7 @@ export class SuggestWidget implements IContentWidget, IDisposable { this.element.style.top = '0'; this.element.style.left = '0'; - if (!this.editor.getConfiguration().iconsInSuggestions) { + if (!this.editor.getConfiguration().contribInfo.iconsInSuggestions) { addClass(this.element, 'no-icons'); } From 8a0da20f7e966ff551daa15427f7f011ac0dd93d Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 6 May 2016 15:01:27 +0200 Subject: [PATCH 088/297] Cursor computes pageSize, not configuration --- .../common/config/commonEditorConfig.ts | 6 - src/vs/editor/common/controller/cursor.ts | 10 +- src/vs/editor/common/controller/oneCursor.ts | 17 +- src/vs/editor/common/editorCommon.ts | 2 - .../test/common/controller/cursor.test.ts | 150 +++++++++--------- 5 files changed, 91 insertions(+), 94 deletions(-) diff --git a/src/vs/editor/common/config/commonEditorConfig.ts b/src/vs/editor/common/config/commonEditorConfig.ts index 903165d19a8..75431ae495d 100644 --- a/src/vs/editor/common/config/commonEditorConfig.ts +++ b/src/vs/editor/common/config/commonEditorConfig.ts @@ -81,7 +81,6 @@ export class InternalEditorOptions implements editorCommon.IInternalEditorOption wrappingInfo: editorCommon.EditorWrappingInfo; contribInfo: editorCommon.EditorContribOptions; lineHeight:number; - pageSize:number; constructor(input:editorCommon.IInternalEditorOptions) { this.wordSeparators = String(input.wordSeparators); @@ -100,7 +99,6 @@ export class InternalEditorOptions implements editorCommon.IInternalEditorOption this.wrappingInfo = input.wrappingInfo.clone(); this.contribInfo = input.contribInfo.clone(); this.lineHeight = Number(input.lineHeight)|0; - this.pageSize = Number(input.pageSize)|0; } } @@ -164,8 +162,6 @@ class InternalEditorOptionsHelper { verticalScrollbarHasArrows: scrollbar.verticalHasArrows }); - let pageSize = Math.floor(layoutInfo.height / fontInfo.lineHeight) - 2; - if (isDominatedByLongLines && wrappingColumn > 0) { // Force viewport width wrapping if model is dominated by long lines wrappingColumn = 0; @@ -264,7 +260,6 @@ class InternalEditorOptionsHelper { contribInfo: contribInfo, lineHeight: fontInfo.lineHeight, // todo -> duplicated in styling - pageSize: pageSize, }; } @@ -325,7 +320,6 @@ class InternalEditorOptionsHelper { wrappingInfo: (!prevOpts.wrappingInfo.equals(newOpts.wrappingInfo)), contribInfo: (!prevOpts.contribInfo.equals(newOpts.contribInfo)), lineHeight: (prevOpts.lineHeight !== newOpts.lineHeight), - pageSize: (prevOpts.pageSize !== newOpts.pageSize), }; } } diff --git a/src/vs/editor/common/controller/cursor.ts b/src/vs/editor/common/controller/cursor.ts index c3476462fee..6c6d1f22228 100644 --- a/src/vs/editor/common/controller/cursor.ts +++ b/src/vs/editor/common/controller/cursor.ts @@ -66,7 +66,7 @@ interface ICommandsData { export class Cursor extends EventEmitter { private editorId:number; - /*private*/ configuration:editorCommon.IConfiguration; + private configuration:editorCommon.IConfiguration; private model:editorCommon.IModel; private modelUnbinds:IDisposable[]; @@ -1288,11 +1288,11 @@ export class Cursor extends EventEmitter { } private _moveDown(inSelectionMode:boolean, isPaged:boolean, ctx: IMultipleCursorOperationContext): boolean { - return this._invokeForAll(ctx, (cursorIndex: number, oneCursor: OneCursor, oneCtx: IOneCursorOperationContext) => OneCursorOp.moveDown(oneCursor, inSelectionMode, isPaged, oneCtx)); + return this._invokeForAll(ctx, (cursorIndex: number, oneCursor: OneCursor, oneCtx: IOneCursorOperationContext) => OneCursorOp.moveDown(oneCursor, inSelectionMode, isPaged, ctx.eventData && ctx.eventData.pageSize || 0, oneCtx)); } private _moveUp(inSelectionMode:boolean, isPaged:boolean, ctx: IMultipleCursorOperationContext): boolean { - return this._invokeForAll(ctx, (cursorIndex: number, oneCursor: OneCursor, oneCtx: IOneCursorOperationContext) => OneCursorOp.moveUp(oneCursor, inSelectionMode, isPaged, oneCtx)); + return this._invokeForAll(ctx, (cursorIndex: number, oneCursor: OneCursor, oneCtx: IOneCursorOperationContext) => OneCursorOp.moveUp(oneCursor, inSelectionMode, isPaged, ctx.eventData && ctx.eventData.pageSize || 0, oneCtx)); } private _moveToBeginningOfLine(inSelectionMode:boolean, ctx: IMultipleCursorOperationContext): boolean { @@ -1451,12 +1451,12 @@ export class Cursor extends EventEmitter { } private _scrollUp(isPaged: boolean, ctx: IMultipleCursorOperationContext): boolean { - ctx.requestScrollDeltaLines = isPaged ? -this.configuration.editor.pageSize : -1; + ctx.requestScrollDeltaLines = isPaged ? -this.cursors.getAll()[0].getPageSize() : -1; return true; } private _scrollDown(isPaged: boolean, ctx: IMultipleCursorOperationContext): boolean { - ctx.requestScrollDeltaLines = isPaged ? this.configuration.editor.pageSize : 1; + ctx.requestScrollDeltaLines = isPaged ? this.cursors.getAll()[0].getPageSize() : 1; return true; } diff --git a/src/vs/editor/common/controller/oneCursor.ts b/src/vs/editor/common/controller/oneCursor.ts index 5b293bf9427..7751d1f5901 100644 --- a/src/vs/editor/common/controller/oneCursor.ts +++ b/src/vs/editor/common/controller/oneCursor.ts @@ -450,6 +450,11 @@ export class OneCursor { // -------------------- START reading API + public getPageSize(): number { + let c = this.configuration.editor; + return Math.floor(c.layoutInfo.height / c.fontInfo.lineHeight) - 2; + } + public getSelectionStart(): editorCommon.IEditorRange { return this.selectionStart; } @@ -675,7 +680,7 @@ export class OneCursorOp { } public static columnSelectUp(isPaged:boolean, cursor:OneCursor, toViewLineNumber: number, toViewVisualColumn: number): IColumnSelectResult { - var linesCount = isPaged ? cursor.configuration.editor.pageSize : 1; + var linesCount = isPaged ? cursor.getPageSize() : 1; toViewLineNumber -= linesCount; if (toViewLineNumber < 1) { @@ -686,7 +691,7 @@ export class OneCursorOp { } public static columnSelectDown(isPaged:boolean, cursor:OneCursor, toViewLineNumber: number, toViewVisualColumn: number): IColumnSelectResult { - var linesCount = isPaged ? cursor.configuration.editor.pageSize : 1; + var linesCount = isPaged ? cursor.getPageSize() : 1; toViewLineNumber += linesCount; if (toViewLineNumber > cursor.getViewLineCount()) { @@ -812,8 +817,8 @@ export class OneCursorOp { return true; } - public static moveDown(cursor:OneCursor, inSelectionMode: boolean, isPaged: boolean, ctx: IOneCursorOperationContext): boolean { - var linesCount = isPaged ? cursor.configuration.editor.pageSize : 1; + public static moveDown(cursor:OneCursor, inSelectionMode: boolean, isPaged: boolean, usePageSize: number, ctx: IOneCursorOperationContext): boolean { + var linesCount = isPaged ? (usePageSize || cursor.getPageSize()) : 1; var viewLineNumber:number, viewColumn:number; @@ -853,8 +858,8 @@ export class OneCursorOp { return true; } - public static moveUp(cursor:OneCursor, inSelectionMode: boolean, isPaged: boolean, ctx: IOneCursorOperationContext): boolean { - var linesCount = isPaged ? cursor.configuration.editor.pageSize : 1; + public static moveUp(cursor:OneCursor, inSelectionMode: boolean, isPaged: boolean, usePageSize: number, ctx: IOneCursorOperationContext): boolean { + var linesCount = isPaged ? (usePageSize || cursor.getPageSize()) : 1; var viewLineNumber:number, viewColumn:number; diff --git a/src/vs/editor/common/editorCommon.ts b/src/vs/editor/common/editorCommon.ts index 8a5904b09b4..059dc2824ca 100644 --- a/src/vs/editor/common/editorCommon.ts +++ b/src/vs/editor/common/editorCommon.ts @@ -903,7 +903,6 @@ export interface IInternalEditorOptions { wordSeparators: string; autoClosingBrackets:boolean; useTabStops: boolean; - pageSize:number; tabFocusMode:boolean; // ---- model options @@ -955,7 +954,6 @@ export interface IConfigurationChangedEvent { wrappingInfo: boolean; contribInfo: boolean; lineHeight: boolean; - pageSize: boolean; } /** diff --git a/src/vs/editor/test/common/controller/cursor.test.ts b/src/vs/editor/test/common/controller/cursor.test.ts index 895777ba96b..0221c68b9ea 100644 --- a/src/vs/editor/test/common/controller/cursor.test.ts +++ b/src/vs/editor/test/common/controller/cursor.test.ts @@ -10,7 +10,7 @@ import {EditOperation} from 'vs/editor/common/core/editOperation'; import {Position} from 'vs/editor/common/core/position'; import {Range} from 'vs/editor/common/core/range'; import {Selection} from 'vs/editor/common/core/selection'; -import {EndOfLinePreference, EventType, Handler, IPosition, ISelection, DefaultEndOfLine, ITextModelCreationOptions} from 'vs/editor/common/editorCommon'; +import {EndOfLinePreference, EventType, Handler, IPosition, ISelection, IEditorOptions, DefaultEndOfLine, ITextModelCreationOptions} from 'vs/editor/common/editorCommon'; import {Model} from 'vs/editor/common/model/model'; import {IMode, IRichEditSupport, IndentAction} from 'vs/editor/common/modes'; import {RichEditSupport} from 'vs/editor/common/modes/supports/richEditSupport'; @@ -21,10 +21,7 @@ let H = Handler; // --------- utils -function cursorCommand(cursor: Cursor, command: string, extraData?: any, sizeProvider?: { pageSize: number; }, overwriteSource?: string) { - if (sizeProvider) { - cursor.configuration.editor.pageSize = sizeProvider.pageSize; // TODO@Alex - } +function cursorCommand(cursor: Cursor, command: string, extraData?: any, overwriteSource?: string) { cursor.trigger(overwriteSource || 'tests', command, extraData); } @@ -64,7 +61,7 @@ function moveDown(cursor: Cursor, linesCount: number, inSelectionMode: boolean = if (linesCount === 1) { cursorCommand(cursor, inSelectionMode ? H.CursorDownSelect : H.CursorDown); } else { - cursorCommand(cursor, inSelectionMode ? H.CursorPageDownSelect : H.CursorPageDown, null, { pageSize: linesCount }); + cursorCommand(cursor, inSelectionMode ? H.CursorPageDownSelect : H.CursorPageDown, { pageSize: linesCount }); } } @@ -72,7 +69,7 @@ function moveUp(cursor: Cursor, linesCount: number, inSelectionMode: boolean = f if (linesCount === 1) { cursorCommand(cursor, inSelectionMode ? H.CursorUpSelect : H.CursorUp); } else { - cursorCommand(cursor, inSelectionMode ? H.CursorPageUpSelect : H.CursorPageUp, null, { pageSize: linesCount }); + cursorCommand(cursor, inSelectionMode ? H.CursorPageUpSelect : H.CursorPageUp, { pageSize: linesCount }); } } @@ -1115,13 +1112,13 @@ suite('Editor Controller - Regression tests', () => { trimAutoWhitespace: false } }, (model, cursor) => { - cursorCommand(cursor, H.Type, { text: '\n' }, null, 'keyboard'); + cursorCommand(cursor, H.Type, { text: '\n' }, 'keyboard'); assert.equal(model.getValue(EndOfLinePreference.LF), '\n', 'assert1'); cursorCommand(cursor, H.Tab, {}); assert.equal(model.getValue(EndOfLinePreference.LF), '\n\t', 'assert2'); - cursorCommand(cursor, H.Type, { text: '\n'}, null, 'keyboard'); + cursorCommand(cursor, H.Type, { text: '\n'}, 'keyboard'); assert.equal(model.getValue(EndOfLinePreference.LF), '\n\t\n\t', 'assert3'); cursorCommand(cursor, H.Type, { text: 'x' }); @@ -1174,13 +1171,13 @@ suite('Editor Controller - Regression tests', () => { moveTo(cursor, 1, 20); - cursorCommand(cursor, H.JumpToBracket, null, null, 'keyboard'); + cursorCommand(cursor, H.JumpToBracket, null, 'keyboard'); cursorEqual(cursor, 1, 10); - cursorCommand(cursor, H.JumpToBracket, null, null, 'keyboard'); + cursorCommand(cursor, H.JumpToBracket, null, 'keyboard'); cursorEqual(cursor, 1, 20); - cursorCommand(cursor, H.JumpToBracket, null, null, 'keyboard'); + cursorCommand(cursor, H.JumpToBracket, null, 'keyboard'); cursorEqual(cursor, 1, 10); }); }); @@ -1207,7 +1204,7 @@ suite('Editor Controller - Regression tests', () => { moveTo(cursor, 4, 1, false); cursorEqual(cursor, 4, 1, 4, 1); - cursorCommand(cursor, H.Tab, null, null, 'keyboard'); + cursorCommand(cursor, H.Tab, null, 'keyboard'); assert.equal(model.getLineContent(4), '\t\t'); }); }); @@ -1228,11 +1225,11 @@ suite('Editor Controller - Regression tests', () => { moveTo(cursor, 1, 2, false); cursorEqual(cursor, 1, 2, 1, 2); - cursorCommand(cursor, H.Indent, null, null, 'keyboard'); + cursorCommand(cursor, H.Indent, null, 'keyboard'); assert.equal(model.getLineContent(1), '\tfunction baz() {'); cursorEqual(cursor, 1, 3, 1, 3); - cursorCommand(cursor, H.Tab, null, null, 'keyboard'); + cursorCommand(cursor, H.Tab, null, 'keyboard'); assert.equal(model.getLineContent(1), '\tf\tunction baz() {'); }); }); @@ -1248,7 +1245,7 @@ suite('Editor Controller - Regression tests', () => { moveTo(cursor, 1, 6, false); cursorEqual(cursor, 1, 6, 1, 6); - cursorCommand(cursor, H.Outdent, null, null, 'keyboard'); + cursorCommand(cursor, H.Outdent, null, 'keyboard'); assert.equal(model.getLineContent(1), ' function baz() {'); cursorEqual(cursor, 1, 5, 1, 5); }); @@ -1264,7 +1261,7 @@ suite('Editor Controller - Regression tests', () => { moveTo(cursor, 1, 7, false); cursorEqual(cursor, 1, 7, 1, 7); - cursorCommand(cursor, H.Outdent, null, null, 'keyboard'); + cursorCommand(cursor, H.Outdent, null, 'keyboard'); assert.equal(model.getLineContent(1), ' '); cursorEqual(cursor, 1, 5, 1, 5); }); @@ -1292,7 +1289,7 @@ suite('Editor Controller - Regression tests', () => { moveTo(cursor, 7, 1, false); cursorEqual(cursor, 7, 1, 7, 1); - cursorCommand(cursor, H.Tab, null, null, 'keyboard'); + cursorCommand(cursor, H.Tab, null, 'keyboard'); assert.equal(model.getLineContent(7), '\t'); cursorEqual(cursor, 7, 2, 7, 2); }); @@ -1310,7 +1307,7 @@ suite('Editor Controller - Regression tests', () => { moveTo(cursor, 2, 1, false); cursorEqual(cursor, 2, 1, 2, 1); - cursorCommand(cursor, H.Cut, null, null, 'keyboard'); + cursorCommand(cursor, H.Cut, null, 'keyboard'); assert.equal(model.getLineCount(), 1); assert.equal(model.getLineContent(1), 'asdasd'); @@ -1328,11 +1325,11 @@ suite('Editor Controller - Regression tests', () => { moveTo(cursor, 2, 1, false); cursorEqual(cursor, 2, 1, 2, 1); - cursorCommand(cursor, H.Cut, null, null, 'keyboard'); + cursorCommand(cursor, H.Cut, null, 'keyboard'); assert.equal(model.getLineCount(), 1); assert.equal(model.getLineContent(1), 'asdasd'); - cursorCommand(cursor, H.Cut, null, null, 'keyboard'); + cursorCommand(cursor, H.Cut, null, 'keyboard'); assert.equal(model.getLineCount(), 1); assert.equal(model.getLineContent(1), ''); @@ -1352,10 +1349,10 @@ suite('Editor Controller - Regression tests', () => { moveTo(cursor, 1, 5, true); cursorEqual(cursor, 1, 5, 1, 3); - cursorCommand(cursor, H.Type, { text: '(' }, null, 'keyboard'); + cursorCommand(cursor, H.Type, { text: '(' }, 'keyboard'); cursorEqual(cursor, 1, 6, 1, 4); - cursorCommand(cursor, H.Type, { text: '(' }, null, 'keyboard'); + cursorCommand(cursor, H.Type, { text: '(' }, 'keyboard'); cursorEqual(cursor, 1, 7, 1, 5); }); }); @@ -1426,7 +1423,7 @@ suite('Editor Controller - Regression tests', () => { model.addListener2(EventType.ModelContentChanged, (e) => { if (isFirst) { isFirst = false; - cursorCommand(cursor, H.Type, { text: '\t' }, null, 'keyboard'); + cursorCommand(cursor, H.Type, { text: '\t' }, 'keyboard'); } }); @@ -1877,8 +1874,8 @@ suite('Editor Controller - Cursor Configuration', () => { ], modelOpts: { insertSpaces: true, tabSize: 4, detectIndentation: false, defaultEOL: DefaultEndOfLine.LF, trimAutoWhitespace: true } }, (model, cursor) => { - cursorCommand(cursor, H.MoveTo, { position: new Position(1, 21) }, null, 'keyboard'); - cursorCommand(cursor, H.Type, { text: '\n' }, null, 'keyboard'); + cursorCommand(cursor, H.MoveTo, { position: new Position(1, 21) }, 'keyboard'); + cursorCommand(cursor, H.Type, { text: '\n' }, 'keyboard'); assert.equal(model.getLineContent(1), ' \tMy First Line\t '); assert.equal(model.getLineContent(2), ' '); }); @@ -1896,57 +1893,57 @@ suite('Editor Controller - Cursor Configuration', () => { modelOpts: { insertSpaces: true, tabSize: 13, detectIndentation: false, defaultEOL: DefaultEndOfLine.LF, trimAutoWhitespace: true } }, (model, cursor) => { // Tab on column 1 - cursorCommand(cursor, H.MoveTo, { position: new Position(2, 1) }, null, 'keyboard'); - cursorCommand(cursor, H.Tab, null, null, 'keyboard'); + cursorCommand(cursor, H.MoveTo, { position: new Position(2, 1) }, 'keyboard'); + cursorCommand(cursor, H.Tab, null, 'keyboard'); assert.equal(model.getLineContent(2), ' My Second Line123'); - cursorCommand(cursor, H.Undo, null, null, 'keyboard'); + cursorCommand(cursor, H.Undo, null, 'keyboard'); // Tab on column 2 assert.equal(model.getLineContent(2), 'My Second Line123'); - cursorCommand(cursor, H.MoveTo, { position: new Position(2, 2) }, null, 'keyboard'); - cursorCommand(cursor, H.Tab, null, null, 'keyboard'); + cursorCommand(cursor, H.MoveTo, { position: new Position(2, 2) }, 'keyboard'); + cursorCommand(cursor, H.Tab, null, 'keyboard'); assert.equal(model.getLineContent(2), 'M y Second Line123'); - cursorCommand(cursor, H.Undo, null, null, 'keyboard'); + cursorCommand(cursor, H.Undo, null, 'keyboard'); // Tab on column 3 assert.equal(model.getLineContent(2), 'My Second Line123'); - cursorCommand(cursor, H.MoveTo, { position: new Position(2, 3) }, null, 'keyboard'); - cursorCommand(cursor, H.Tab, null, null, 'keyboard'); + cursorCommand(cursor, H.MoveTo, { position: new Position(2, 3) }, 'keyboard'); + cursorCommand(cursor, H.Tab, null, 'keyboard'); assert.equal(model.getLineContent(2), 'My Second Line123'); - cursorCommand(cursor, H.Undo, null, null, 'keyboard'); + cursorCommand(cursor, H.Undo, null, 'keyboard'); // Tab on column 4 assert.equal(model.getLineContent(2), 'My Second Line123'); - cursorCommand(cursor, H.MoveTo, { position: new Position(2, 4) }, null, 'keyboard'); - cursorCommand(cursor, H.Tab, null, null, 'keyboard'); + cursorCommand(cursor, H.MoveTo, { position: new Position(2, 4) }, 'keyboard'); + cursorCommand(cursor, H.Tab, null, 'keyboard'); assert.equal(model.getLineContent(2), 'My Second Line123'); - cursorCommand(cursor, H.Undo, null, null, 'keyboard'); + cursorCommand(cursor, H.Undo, null, 'keyboard'); // Tab on column 5 assert.equal(model.getLineContent(2), 'My Second Line123'); - cursorCommand(cursor, H.MoveTo, { position: new Position(2, 5) }, null, 'keyboard'); - cursorCommand(cursor, H.Tab, null, null, 'keyboard'); + cursorCommand(cursor, H.MoveTo, { position: new Position(2, 5) }, 'keyboard'); + cursorCommand(cursor, H.Tab, null, 'keyboard'); assert.equal(model.getLineContent(2), 'My S econd Line123'); - cursorCommand(cursor, H.Undo, null, null, 'keyboard'); + cursorCommand(cursor, H.Undo, null, 'keyboard'); // Tab on column 5 assert.equal(model.getLineContent(2), 'My Second Line123'); - cursorCommand(cursor, H.MoveTo, { position: new Position(2, 5) }, null, 'keyboard'); - cursorCommand(cursor, H.Tab, null, null, 'keyboard'); + cursorCommand(cursor, H.MoveTo, { position: new Position(2, 5) }, 'keyboard'); + cursorCommand(cursor, H.Tab, null, 'keyboard'); assert.equal(model.getLineContent(2), 'My S econd Line123'); - cursorCommand(cursor, H.Undo, null, null, 'keyboard'); + cursorCommand(cursor, H.Undo, null, 'keyboard'); // Tab on column 13 assert.equal(model.getLineContent(2), 'My Second Line123'); - cursorCommand(cursor, H.MoveTo, { position: new Position(2, 13) }, null, 'keyboard'); - cursorCommand(cursor, H.Tab, null, null, 'keyboard'); + cursorCommand(cursor, H.MoveTo, { position: new Position(2, 13) }, 'keyboard'); + cursorCommand(cursor, H.Tab, null, 'keyboard'); assert.equal(model.getLineContent(2), 'My Second Li ne123'); - cursorCommand(cursor, H.Undo, null, null, 'keyboard'); + cursorCommand(cursor, H.Undo, null, 'keyboard'); // Tab on column 14 assert.equal(model.getLineContent(2), 'My Second Line123'); - cursorCommand(cursor, H.MoveTo, { position: new Position(2, 14) }, null, 'keyboard'); - cursorCommand(cursor, H.Tab, null, null, 'keyboard'); + cursorCommand(cursor, H.MoveTo, { position: new Position(2, 14) }, 'keyboard'); + cursorCommand(cursor, H.Tab, null, 'keyboard'); assert.equal(model.getLineContent(2), 'My Second Lin e123'); }); }); @@ -1962,7 +1959,7 @@ suite('Editor Controller - Cursor Configuration', () => { moveTo(cursor, 1, 7, false); cursorEqual(cursor, 1, 7, 1, 7); - cursorCommand(cursor, H.Type, { text: '\n' }, null, 'keyboard'); + cursorCommand(cursor, H.Type, { text: '\n' }, 'keyboard'); assert.equal(model.getValue(EndOfLinePreference.CRLF), '\thello\r\n '); }); }); @@ -1978,7 +1975,7 @@ suite('Editor Controller - Cursor Configuration', () => { moveTo(cursor, 1, 7, false); cursorEqual(cursor, 1, 7, 1, 7); - cursorCommand(cursor, H.Type, { text: '\n' }, null, 'keyboard'); + cursorCommand(cursor, H.Type, { text: '\n' }, 'keyboard'); assert.equal(model.getValue(EndOfLinePreference.CRLF), '\thello\r\n '); }); }); @@ -1994,7 +1991,7 @@ suite('Editor Controller - Cursor Configuration', () => { moveTo(cursor, 1, 7, false); cursorEqual(cursor, 1, 7, 1, 7); - cursorCommand(cursor, H.Type, { text: '\n' }, null, 'keyboard'); + cursorCommand(cursor, H.Type, { text: '\n' }, 'keyboard'); assert.equal(model.getValue(EndOfLinePreference.CRLF), '\thell(\r\n \r\n )'); }); }); @@ -2011,7 +2008,7 @@ suite('Editor Controller - Cursor Configuration', () => { moveTo(cursor, lineNumber, column, false); cursorEqual(cursor, lineNumber, column, lineNumber, column); - cursorCommand(cursor, H.LineInsertBefore, null, null, 'keyboard'); + cursorCommand(cursor, H.LineInsertBefore, null, 'keyboard'); callback(model, cursor); }); }; @@ -2053,7 +2050,7 @@ suite('Editor Controller - Cursor Configuration', () => { moveTo(cursor, lineNumber, column, false); cursorEqual(cursor, lineNumber, column, lineNumber, column); - cursorCommand(cursor, H.LineInsertAfter, null, null, 'keyboard'); + cursorCommand(cursor, H.LineInsertAfter, null, 'keyboard'); callback(model, cursor); }); }; @@ -2099,12 +2096,12 @@ suite('Editor Controller - Cursor Configuration', () => { // Move cursor to the end, verify that we do not trim whitespaces if line has values moveTo(cursor, 1, model.getLineContent(1).length + 1); - cursorCommand(cursor, H.Type, { text: '\n' }, null, 'keyboard'); + cursorCommand(cursor, H.Type, { text: '\n' }, 'keyboard'); assert.equal(model.getLineContent(1), ' some line abc '); assert.equal(model.getLineContent(2), ' '); // Try to enter again, we should trimmed previous line - cursorCommand(cursor, H.Type, { text: '\n' }, null, 'keyboard'); + cursorCommand(cursor, H.Type, { text: '\n' }, 'keyboard'); assert.equal(model.getLineContent(1), ' some line abc '); assert.equal(model.getLineContent(2), ' '); assert.equal(model.getLineContent(3), ' '); @@ -2125,11 +2122,11 @@ suite('Editor Controller - Cursor Configuration', () => { } }, (model, cursor) => { moveTo(cursor, 1, model.getLineContent(1).length + 1); - cursorCommand(cursor, H.Type, { text: '\n' }, null, 'keyboard'); + cursorCommand(cursor, H.Type, { text: '\n' }, 'keyboard'); assert.equal(model.getLineContent(1), ' '); assert.equal(model.getLineContent(2), ' '); - cursorCommand(cursor, H.Type, { text: '\n' }, null, 'keyboard'); + cursorCommand(cursor, H.Type, { text: '\n' }, 'keyboard'); assert.equal(model.getLineContent(1), ' '); assert.equal(model.getLineContent(2), ''); assert.equal(model.getLineContent(3), ' '); @@ -2155,7 +2152,7 @@ suite('Editor Controller - Cursor Configuration', () => { }, (model, cursor) => { moveTo(cursor, 3, 1); - cursorCommand(cursor, H.Tab, null, null, 'keyboard'); + cursorCommand(cursor, H.Tab, null, 'keyboard'); assert.equal(model.getLineContent(1), ' if (a) {'); assert.equal(model.getLineContent(2), ' '); assert.equal(model.getLineContent(3), ' '); @@ -2163,7 +2160,7 @@ suite('Editor Controller - Cursor Configuration', () => { assert.equal(model.getLineContent(5), ' }'); moveTo(cursor, 4, 1); - cursorCommand(cursor, H.Tab, null, null, 'keyboard'); + cursorCommand(cursor, H.Tab, null, 'keyboard'); assert.equal(model.getLineContent(1), ' if (a) {'); assert.equal(model.getLineContent(2), ' '); assert.equal(model.getLineContent(3), ''); @@ -2171,7 +2168,7 @@ suite('Editor Controller - Cursor Configuration', () => { assert.equal(model.getLineContent(5), ' }'); moveTo(cursor, 5, model.getLineMaxColumn(5)); - cursorCommand(cursor, H.Type, { text: 'something' }, null, 'keyboard'); + cursorCommand(cursor, H.Type, { text: 'something' }, 'keyboard'); assert.equal(model.getLineContent(1), ' if (a) {'); assert.equal(model.getLineContent(2), ' '); assert.equal(model.getLineContent(3), ''); @@ -2196,24 +2193,24 @@ suite('Editor Controller - Cursor Configuration', () => { // Move cursor to the end, verify that we do not trim whitespaces if line has values moveTo(cursor, 1, model.getLineContent(1).length + 1); - cursorCommand(cursor, H.Type, { text: '\n' }, null, 'keyboard'); + cursorCommand(cursor, H.Type, { text: '\n' }, 'keyboard'); assert.equal(model.getLineContent(1), ' some line abc '); assert.equal(model.getLineContent(2), ' '); // Try to enter again, we should trimmed previous line - cursorCommand(cursor, H.Type, { text: '\n' }, null, 'keyboard'); + cursorCommand(cursor, H.Type, { text: '\n' }, 'keyboard'); assert.equal(model.getLineContent(1), ' some line abc '); assert.equal(model.getLineContent(2), ''); assert.equal(model.getLineContent(3), ' '); // More whitespaces - cursorCommand(cursor, H.Tab, null, null, 'keyboard'); + cursorCommand(cursor, H.Tab, null, 'keyboard'); assert.equal(model.getLineContent(1), ' some line abc '); assert.equal(model.getLineContent(2), ''); assert.equal(model.getLineContent(3), ' '); // Enter and verify that trimmed again - cursorCommand(cursor, H.Type, { text: '\n' }, null, 'keyboard'); + cursorCommand(cursor, H.Type, { text: '\n' }, 'keyboard'); assert.equal(model.getLineContent(1), ' some line abc '); assert.equal(model.getLineContent(2), ''); assert.equal(model.getLineContent(3), ''); @@ -2221,7 +2218,7 @@ suite('Editor Controller - Cursor Configuration', () => { // Trimmed if we will keep only text moveTo(cursor, 1, 5); - cursorCommand(cursor, H.Type, { text: '\n' }, null, 'keyboard'); + cursorCommand(cursor, H.Type, { text: '\n' }, 'keyboard'); assert.equal(model.getLineContent(1), ' '); assert.equal(model.getLineContent(2), ' some line abc '); assert.equal(model.getLineContent(3), ''); @@ -2231,7 +2228,7 @@ suite('Editor Controller - Cursor Configuration', () => { // Trimmed if we will keep only text by selection moveTo(cursor, 2, 5); moveTo(cursor, 3, 1, true); - cursorCommand(cursor, H.Type, { text: '\n' }, null, 'keyboard'); + cursorCommand(cursor, H.Type, { text: '\n' }, 'keyboard'); assert.equal(model.getLineContent(1), ' '); assert.equal(model.getLineContent(2), ' '); assert.equal(model.getLineContent(3), ''); @@ -2253,10 +2250,11 @@ suite('Editor Controller - Cursor Configuration', () => { detectIndentation: false, defaultEOL: DefaultEndOfLine.LF, trimAutoWhitespace: true + }, + editorOpts: { + useTabStops: false } }, (model, cursor) => { - cursor.configuration.editor.useTabStops = false; - // DeleteLeft removes just one whitespace moveTo(cursor, 2, 9); cursorCommand(cursor, H.DeleteLeft, {}); @@ -2277,10 +2275,11 @@ suite('Editor Controller - Cursor Configuration', () => { detectIndentation: false, defaultEOL: DefaultEndOfLine.LF, trimAutoWhitespace: true + }, + editorOpts: { + useTabStops: true } }, (model, cursor) => { - cursor.configuration.editor.useTabStops = true; - // DeleteLeft does not remove tab size, because some text exists before moveTo(cursor, 2, model.getLineContent(2).length + 1); cursorCommand(cursor, H.DeleteLeft, {}); @@ -2348,16 +2347,16 @@ suite('Editor Controller - Cursor Configuration', () => { trimAutoWhitespace: true } }, (model, cursor) => { - cursorCommand(cursor, H.Type, { text: '\n' }, null, 'keyboard'); + cursorCommand(cursor, H.Type, { text: '\n' }, 'keyboard'); assert.equal(model.getValue(EndOfLinePreference.LF), '\n', 'assert1'); cursorCommand(cursor, H.Tab, {}); assert.equal(model.getValue(EndOfLinePreference.LF), '\n\t', 'assert2'); - cursorCommand(cursor, H.Type, { text: 'y'}, null, 'keyboard'); + cursorCommand(cursor, H.Type, { text: 'y'}, 'keyboard'); assert.equal(model.getValue(EndOfLinePreference.LF), '\n\ty', 'assert2'); - cursorCommand(cursor, H.Type, { text: '\n'}, null, 'keyboard'); + cursorCommand(cursor, H.Type, { text: '\n'}, 'keyboard'); assert.equal(model.getValue(EndOfLinePreference.LF), '\n\ty\n\t', 'assert3'); cursorCommand(cursor, H.Type, { text: 'x' }); @@ -2406,11 +2405,12 @@ interface ICursorOpts { text: string[]; mode?: IMode; modelOpts?: ITextModelCreationOptions; + editorOpts?: IEditorOptions; } function usingCursor(opts:ICursorOpts, callback:(model:Model, cursor:Cursor)=>void): void { let model = new Model(opts.text.join('\n'), opts.modelOpts || Model.DEFAULT_CREATION_OPTIONS, opts.mode); - let config = new MockConfiguration(null); + let config = new MockConfiguration(opts.editorOpts); let cursor = new Cursor(1, config, model, null, false); callback(model, cursor); From 9e1420c5f1296dba69bf7d6b8cd53ec6e274a0be Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 6 May 2016 14:52:23 +0200 Subject: [PATCH 089/297] :lipstick: ai appender --- .../telemetry/node/appInsightsAppender.ts | 42 ++++++++----------- src/vs/workbench/electron-browser/shell.ts | 2 +- 2 files changed, 19 insertions(+), 25 deletions(-) diff --git a/src/vs/platform/telemetry/node/appInsightsAppender.ts b/src/vs/platform/telemetry/node/appInsightsAppender.ts index 2a71bc85193..362f03f9bb2 100644 --- a/src/vs/platform/telemetry/node/appInsightsAppender.ts +++ b/src/vs/platform/telemetry/node/appInsightsAppender.ts @@ -7,16 +7,16 @@ import errors = require('vs/base/common/errors'); import {IStorageService} from 'vs/platform/storage/common/storage'; import {ITelemetryAppender} from 'vs/platform/telemetry/common/telemetry'; -import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace'; +import {IEnvironment} from 'vs/platform/workspace/common/workspace'; import {AIAdapter, IAIAdapter} from 'vs/base/node/aiAdapter'; import winreg = require('winreg'); import os = require('os'); -class StorageKeys { - public static sqmUserId: string = 'telemetry.sqm.userId'; - public static sqmMachineId: string = 'telemetry.sqm.machineId'; - public static lastSessionDate: string = 'telemetry.lastSessionDate'; - public static firstSessionDate: string = 'telemetry.firstSessionDate'; +namespace StorageKeys { + export const sqmUserId: string = 'telemetry.sqm.userId'; + export const sqmMachineId: string = 'telemetry.sqm.machineId'; + export const lastSessionDate: string = 'telemetry.lastSessionDate'; + export const firstSessionDate: string = 'telemetry.firstSessionDate'; } export class AppInsightsAppender implements ITelemetryAppender { @@ -25,29 +25,23 @@ export class AppInsightsAppender implements ITelemetryAppender { private static SQM_KEY: string = '\\Software\\Microsoft\\SQMClient'; - private storageService:IStorageService; - private contextService: IWorkspaceContextService; - + private storageService: IStorageService; private appInsights: IAIAdapter; private appInsightsVortex: IAIAdapter; - - protected commonProperties: {[key:string] : string}; - protected commonMetrics: {[key: string]: number}; + private commonProperties: { [key: string]: string }; + private commonMetrics: { [key: string]: number }; constructor( @IStorageService storageService: IStorageService, - @IWorkspaceContextService contextService: IWorkspaceContextService, + env: IEnvironment, _testing_client?: any ) { this.commonProperties = {}; this.commonMetrics = {}; - - this.contextService = contextService; this.storageService = storageService; - let config = this.contextService.getConfiguration().env.aiConfig; - let key = config ? config.key: null; - let asimovKey = config ? config.asimovKey: null; + let key = env.aiConfig && env.aiConfig.key; + let asimovKey = env.aiConfig && env.aiConfig.asimovKey; // for test if (_testing_client) { @@ -63,7 +57,7 @@ export class AppInsightsAppender implements ITelemetryAppender { this.appInsights = new AIAdapter(key, AppInsightsAppender.EVENT_NAME_PREFIX); } - if(asimovKey) { + if (asimovKey) { this.appInsightsVortex = new AIAdapter(asimovKey, AppInsightsAppender.EVENT_NAME_PREFIX); } @@ -83,7 +77,7 @@ export class AppInsightsAppender implements ITelemetryAppender { if (sqmUserId) { this.commonProperties['sqm.userid'] = sqmUserId; } else { - this.getWinRegKeyData(AppInsightsAppender.SQM_KEY, 'UserId', winreg.HKCU, (error, result: string) => { + AppInsightsAppender._getWinRegKeyData(AppInsightsAppender.SQM_KEY, 'UserId', winreg.HKCU, (error, result: string) => { if (!error && result) { this.commonProperties['sqm.userid'] = result; this.storageService.store(StorageKeys.sqmUserId, result); @@ -96,7 +90,7 @@ export class AppInsightsAppender implements ITelemetryAppender { this.commonProperties['sqm.machineid'] = sqmMachineId; } else { - this.getWinRegKeyData(AppInsightsAppender.SQM_KEY, 'MachineId', winreg.HKLM,(error, result) => { + AppInsightsAppender._getWinRegKeyData(AppInsightsAppender.SQM_KEY, 'MachineId', winreg.HKLM, (error, result) => { if (!error && result) { this.commonProperties['sqm.machineid'] = result; this.storageService.store(StorageKeys.sqmMachineId, result); @@ -106,7 +100,7 @@ export class AppInsightsAppender implements ITelemetryAppender { } var firstSessionDate = this.storageService.get(StorageKeys.firstSessionDate); - if(!firstSessionDate) { + if (!firstSessionDate) { firstSessionDate = (new Date()).toUTCString(); this.storageService.store(StorageKeys.firstSessionDate, firstSessionDate); } @@ -114,7 +108,7 @@ export class AppInsightsAppender implements ITelemetryAppender { //report last session date and isNewSession flag var lastSessionDate = this.storageService.get(StorageKeys.lastSessionDate); - if(!lastSessionDate) { + if (!lastSessionDate) { this.commonMetrics['isNewSession'] = 1; } else { this.commonMetrics['isNewSession'] = 0; @@ -128,7 +122,7 @@ export class AppInsightsAppender implements ITelemetryAppender { } } - private getWinRegKeyData(key: string, name: string, hive: string, callback: (error: Error, userId: string) => void): void { + private static _getWinRegKeyData(key: string, name: string, hive: string, callback: (error: Error, userId: string) => void): void { if (process.platform === 'win32') { try { var reg = new winreg({ diff --git a/src/vs/workbench/electron-browser/shell.ts b/src/vs/workbench/electron-browser/shell.ts index e44c2d5bc5a..9d2a41e984e 100644 --- a/src/vs/workbench/electron-browser/shell.ts +++ b/src/vs/workbench/electron-browser/shell.ts @@ -209,7 +209,7 @@ export class WorkbenchShell { extensionsRoot: this.configuration.env.userExtensionsHome, version: this.configuration.env.version, commitHash: this.configuration.env.commitHash, - appender: [new AppInsightsAppender(this.storageService, this.contextService)] + appender: [new AppInsightsAppender(this.storageService, this.configuration.env)] }); } else { this.telemetryService = NullTelemetryService; From 6b300882b9b557df5412ce8f443db231f1a1b383 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 6 May 2016 15:05:19 +0200 Subject: [PATCH 090/297] use safeCall when announcing new height to zone, fixes regression --- src/vs/editor/browser/viewParts/viewZones/viewZones.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/editor/browser/viewParts/viewZones/viewZones.ts b/src/vs/editor/browser/viewParts/viewZones/viewZones.ts index 2e7cdd6515d..c14aead1c17 100644 --- a/src/vs/editor/browser/viewParts/viewZones/viewZones.ts +++ b/src/vs/editor/browser/viewParts/viewZones/viewZones.ts @@ -219,7 +219,7 @@ export class ViewZones extends ViewPart { // TODO@Alex: change `newOrdinal` too if (changed) { - zone.delegate.onComputedHeight(props.heightInPx); + this._safeCallOnComputedHeight(zone.delegate, props.heightInPx); this.setShouldRender(); } } From a2f2f4b02bcd8edb557438fe31b06feb1cfc735e Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 6 May 2016 15:33:59 +0200 Subject: [PATCH 091/297] fix test failure --- .../test/node/appInsightsAppender.test.ts | 30 +++++++++---------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/src/vs/platform/telemetry/test/node/appInsightsAppender.test.ts b/src/vs/platform/telemetry/test/node/appInsightsAppender.test.ts index a69f4ebe8d5..8d47c26610f 100644 --- a/src/vs/platform/telemetry/test/node/appInsightsAppender.test.ts +++ b/src/vs/platform/telemetry/test/node/appInsightsAppender.test.ts @@ -37,21 +37,19 @@ class AIAdapterMock implements IAIAdapter { } } -class ContextServiceMock { - - constructor(private key?: string, private asimovKey?: string) {} - - getConfiguration(): any { - return { - env: { - aiConfig: { - key: this.key, - asimovKey: this.asimovKey - } - } - }; +let envKeyNoAsimov: any = { + aiConfig: { + key: '123', + asimovKey: undefined } -} +}; + +let envKeyAsimov: any = { + aiConfig: { + key: '123', + asimovKey: 'AIF-123' + } +}; suite('Telemetry - AppInsightsTelemetryAppender', () => { var appInsightsMock: AIAdapterMock; @@ -59,7 +57,7 @@ suite('Telemetry - AppInsightsTelemetryAppender', () => { setup(() => { appInsightsMock = new AIAdapterMock(AppInsightsAppender.EVENT_NAME_PREFIX, AppInsightsAppender.EVENT_NAME_PREFIX); - appender = new AppInsightsAppender(null, new ContextServiceMock('123'), appInsightsMock); + appender = new AppInsightsAppender(null, envKeyNoAsimov, appInsightsMock); }); teardown(() => { @@ -90,7 +88,7 @@ suite('Telemetry - AppInsightsTelemetryAppender', () => { }); test('Test asimov', () => { - appender = new AppInsightsAppender(null, new ContextServiceMock('123', 'AIF-123'), appInsightsMock); + appender = new AppInsightsAppender(null, envKeyAsimov, appInsightsMock); appender.log('testEvent'); From 26769ff0b9255ba910b2909fec37474c3880ff20 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 6 May 2016 15:35:53 +0200 Subject: [PATCH 092/297] Convert IInternalEditorOptions to InternalEditorOptions --- .../browser/viewLayout/scrollManager.ts | 4 +- .../browser/viewParts/lines/viewLine.ts | 17 --- .../overviewRuler/decorationsOverviewRuler.ts | 6 +- .../editor/browser/widget/codeEditorWidget.ts | 4 +- .../editor/browser/widget/diffEditorWidget.ts | 4 +- src/vs/editor/common/commonCodeEditor.ts | 2 +- .../common/config/commonEditorConfig.ts | 137 +++--------------- src/vs/editor/common/config/defaultConfig.ts | 2 +- src/vs/editor/common/editorCommon.ts | 129 ++++++++++++----- src/vs/editor/common/model/textModel.ts | 4 +- .../common/services/modelServiceImpl.ts | 4 +- 11 files changed, 129 insertions(+), 184 deletions(-) diff --git a/src/vs/editor/browser/viewLayout/scrollManager.ts b/src/vs/editor/browser/viewLayout/scrollManager.ts index a84107bdecd..fed40b8435f 100644 --- a/src/vs/editor/browser/viewLayout/scrollManager.ts +++ b/src/vs/editor/browser/viewLayout/scrollManager.ts @@ -40,7 +40,7 @@ export class ScrollManager implements IDisposable { listenOnDomNode: viewDomNode, vertical: configScrollbarOpts.vertical, horizontal: configScrollbarOpts.horizontal, - className: ClassNames.SCROLLABLE_ELEMENT + ' ' + this.configuration.editor.theme, + className: ClassNames.SCROLLABLE_ELEMENT + ' ' + this.configuration.editor.viewInfo.theme, useShadows: false, lazyRender: true, saveLastScrollTimeOnClassName: ClassNames.VIEW_LINE @@ -63,7 +63,7 @@ export class ScrollManager implements IDisposable { })); this.toDispose.push(this.configuration.onDidChange((e:IConfigurationChangedEvent) => { - this.scrollbar.updateClassName(this.configuration.editor.theme); + this.scrollbar.updateClassName(ClassNames.SCROLLABLE_ELEMENT + ' ' + this.configuration.editor.viewInfo.theme); if (e.viewInfo.scrollbar) { let newOpts:ScrollableElementChangeOptions = { canUseTranslate3d: true, diff --git a/src/vs/editor/browser/viewParts/lines/viewLine.ts b/src/vs/editor/browser/viewParts/lines/viewLine.ts index 4bbfbdddfca..c1541bf1c9b 100644 --- a/src/vs/editor/browser/viewParts/lines/viewLine.ts +++ b/src/vs/editor/browser/viewParts/lines/viewLine.ts @@ -23,7 +23,6 @@ export class ViewLine implements IVisibleLineData { private _spaceWidth: number; private _lineHeight: number; private _stopRenderingLineAfter: number; - protected _fontLigatures: boolean; private _domNode: FastDomNode; @@ -43,7 +42,6 @@ export class ViewLine implements IVisibleLineData { this._spaceWidth = this._context.configuration.editor.fontInfo.spaceWidth; this._lineHeight = this._context.configuration.editor.lineHeight; this._stopRenderingLineAfter = this._context.configuration.editor.viewInfo.stopRenderingLineAfter; - this._fontLigatures = this._context.configuration.editor.fontLigatures; this._domNode = null; this._isInvalid = true; @@ -99,9 +97,6 @@ export class ViewLine implements IVisibleLineData { if (e.viewInfo.stopRenderingLineAfter) { this._stopRenderingLineAfter = this._context.configuration.editor.viewInfo.stopRenderingLineAfter; } - if (e.fontLigatures) { - this._fontLigatures = this._context.configuration.editor.fontLigatures; - } this._isInvalid = true; } @@ -312,18 +307,6 @@ class WebKitViewLine extends ViewLine { protected _readVisibleRangesForRange(startColumn:number, endColumn:number, clientRectDeltaLeft:number, endNode:HTMLElement): HorizontalRange[] { let output = super._readVisibleRangesForRange(startColumn, endColumn, clientRectDeltaLeft, endNode); - if (this._fontLigatures && output.length === 1 && endColumn > 1 && endColumn === this._charOffsetInPart.length) { - let lastSpanBoundingClientRect = (this._getReadingTarget().lastChild).getBoundingClientRect(); - let lastSpanBoundingClientRectRight = lastSpanBoundingClientRect.right - clientRectDeltaLeft; - if (startColumn === endColumn) { - output[0].left = lastSpanBoundingClientRectRight; - output[0].width = 0; - } else { - output[0].width = lastSpanBoundingClientRectRight - output[0].left; - } - return output; - } - if (!output || output.length === 0 || startColumn === endColumn || (startColumn === 1 && endColumn === this._charOffsetInPart.length)) { return output; } diff --git a/src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler.ts b/src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler.ts index fb458999068..88b7b97b714 100644 --- a/src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler.ts +++ b/src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler.ts @@ -42,7 +42,7 @@ export class DecorationsOverviewRuler extends ViewPart { getVerticalOffsetForLine ); this._overviewRuler.setLanesCount(this._context.configuration.editor.viewInfo.overviewRulerLanes, false); - let theme = this._context.configuration.editor.theme; + let theme = this._context.configuration.editor.viewInfo.theme; this._overviewRuler.setUseDarkColor(!themes.isLightTheme(theme), false); this._shouldUpdateDecorations = true; @@ -91,8 +91,8 @@ export class DecorationsOverviewRuler extends ViewPart { shouldRender = true; } - if (e.theme) { - let theme = this._context.configuration.editor.theme; + if (e.viewInfo.theme) { + let theme = this._context.configuration.editor.viewInfo.theme; this._overviewRuler.setUseDarkColor(!themes.isLightTheme(theme), false); shouldRender = true; } diff --git a/src/vs/editor/browser/widget/codeEditorWidget.ts b/src/vs/editor/browser/widget/codeEditorWidget.ts index 271d94561ed..2df72cd3d74 100644 --- a/src/vs/editor/browser/widget/codeEditorWidget.ts +++ b/src/vs/editor/browser/widget/codeEditorWidget.ts @@ -91,9 +91,9 @@ export class CodeEditorWidget extends CommonCodeEditor implements editorBrowser. } public updateOptions(newOptions:editorCommon.IEditorOptions): void { - let oldTheme = this._configuration.editor.theme; + let oldTheme = this._configuration.editor.viewInfo.theme; super.updateOptions(newOptions); - let newTheme = this._configuration.editor.theme; + let newTheme = this._configuration.editor.viewInfo.theme; if (oldTheme !== newTheme) { this.render(); diff --git a/src/vs/editor/browser/widget/diffEditorWidget.ts b/src/vs/editor/browser/widget/diffEditorWidget.ts index 67d7245a3f6..da70e56125c 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget.ts @@ -1718,7 +1718,7 @@ class DiffEdtorWidgetInline extends DiffEditorWidgetStyle implements IDiffEditor class InlineViewZonesComputer extends ViewZonesComputer { private originalModel:editorCommon.IModel; - private modifiedEditorConfiguration:editorCommon.IInternalEditorOptions; + private modifiedEditorConfiguration:editorCommon.InternalEditorOptions; private modifiedEditorTabSize:number; constructor(lineChanges:editorCommon.ILineChange[], originalForeignVZ:editorCommon.IEditorWhitespace[], modifiedForeignVZ:editorCommon.IEditorWhitespace[], originalEditor:editorBrowser.ICodeEditor, modifiedEditor:editorBrowser.ICodeEditor) { @@ -1773,7 +1773,7 @@ class InlineViewZonesComputer extends ViewZonesComputer { }; } - private renderOriginalLine(count:number, originalModel:editorCommon.IModel, config:editorCommon.IInternalEditorOptions, tabSize:number, lineNumber:number, decorations:editorCommon.IModelDecoration[]): string[] { + private renderOriginalLine(count:number, originalModel:editorCommon.IModel, config:editorCommon.InternalEditorOptions, tabSize:number, lineNumber:number, decorations:editorCommon.IModelDecoration[]): string[] { let lineContent = originalModel.getLineContent(lineNumber); let lineTokens = new ViewLineTokens([new ViewLineToken(0, '')], 0, lineContent.length); diff --git a/src/vs/editor/common/commonCodeEditor.ts b/src/vs/editor/common/commonCodeEditor.ts index 54cc47df599..89bb026ee85 100644 --- a/src/vs/editor/common/commonCodeEditor.ts +++ b/src/vs/editor/common/commonCodeEditor.ts @@ -181,7 +181,7 @@ export abstract class CommonCodeEditor extends EventEmitter implements IActionPr } } - public getConfiguration(): editorCommon.IInternalEditorOptions { + public getConfiguration(): editorCommon.InternalEditorOptions { return this._configuration.editorClone; } diff --git a/src/vs/editor/common/config/commonEditorConfig.ts b/src/vs/editor/common/config/commonEditorConfig.ts index 75431ae495d..b83f7e5f8d8 100644 --- a/src/vs/editor/common/config/commonEditorConfig.ts +++ b/src/vs/editor/common/config/commonEditorConfig.ts @@ -11,7 +11,7 @@ import * as objects from 'vs/base/common/objects'; import * as platform from 'vs/base/common/platform'; import {Extensions, IConfigurationRegistry, IConfigurationNode} from 'vs/platform/configuration/common/configurationRegistry'; import {Registry} from 'vs/platform/platform'; -import {DefaultConfig, DEFAULT_INDENTATION, GOLDEN_LINE_HEIGHT_RATIO} from 'vs/editor/common/config/defaultConfig'; +import {DefaultConfig, DEFAULT_INDENTATION, DEFAULT_TRIM_AUTO_WHITESPACE, GOLDEN_LINE_HEIGHT_RATIO} from 'vs/editor/common/config/defaultConfig'; import * as editorCommon from 'vs/editor/common/editorCommon'; import {EditorLayoutProvider} from 'vs/editor/common/viewLayout/editorLayoutProvider'; import {ScrollbarVisibility} from 'vs/base/browser/ui/scrollbar/scrollableElementOptions'; @@ -62,46 +62,6 @@ export class ConfigurationWithDefaults { } } -export class InternalEditorOptions implements editorCommon.IInternalEditorOptions { - _internalEditorOptionsBrand: void; - - wordSeparators: string; - theme:string; - readOnly:boolean; - fontLigatures:boolean; - tabFocusMode:boolean; - stopLineTokenizationAfter:number; - longLineBoundary:number; - autoClosingBrackets:boolean; - useTabStops: boolean; - trimAutoWhitespace: boolean; - layoutInfo: editorCommon.EditorLayoutInfo; - fontInfo: editorCommon.FontInfo; - viewInfo: editorCommon.InternalEditorViewOptions; - wrappingInfo: editorCommon.EditorWrappingInfo; - contribInfo: editorCommon.EditorContribOptions; - lineHeight:number; - - constructor(input:editorCommon.IInternalEditorOptions) { - this.wordSeparators = String(input.wordSeparators); - this.theme = String(input.theme); - this.readOnly = Boolean(input.readOnly); - this.fontLigatures = Boolean(input.fontLigatures); - this.tabFocusMode = Boolean(input.tabFocusMode); - this.stopLineTokenizationAfter = Number(input.stopLineTokenizationAfter)|0; - this.longLineBoundary = Number(input.longLineBoundary)|0; - this.autoClosingBrackets = Boolean(input.autoClosingBrackets); - this.useTabStops = Boolean(input.useTabStops); - this.trimAutoWhitespace = Boolean(input.trimAutoWhitespace); - this.layoutInfo = input.layoutInfo.clone(); - this.fontInfo = input.fontInfo.clone(); - this.viewInfo = input.viewInfo.clone(); - this.wrappingInfo = input.wrappingInfo.clone(); - this.contribInfo = input.contribInfo.clone(); - this.lineHeight = Number(input.lineHeight)|0; - } -} - class InternalEditorOptionsHelper { constructor() { @@ -114,7 +74,7 @@ class InternalEditorOptionsHelper { editorClassName:string, isDominatedByLongLines:boolean, lineCount: number - ): editorCommon.IInternalEditorOptions { + ): editorCommon.InternalEditorOptions { let wrappingColumn = toInteger(opts.wrappingColumn, -1); @@ -203,6 +163,7 @@ class InternalEditorOptionsHelper { } let viewInfo = new editorCommon.InternalEditorViewOptions({ + theme: opts.theme, experimentalScreenReader: toBoolean(opts.experimentalScreenReader), rulers: toSortedIntegerArray(opts.rulers), ariaLabel: String(opts.ariaLabel), @@ -239,28 +200,21 @@ class InternalEditorOptionsHelper { folding: toBoolean(opts.folding), }); - return { - // ---- Options that are transparent - get no massaging - theme: opts.theme, - readOnly: readOnly, - wordSeparators: String(opts.wordSeparators), - fontLigatures: toBoolean(opts.fontLigatures), - tabFocusMode: tabFocusMode, + return new editorCommon.InternalEditorOptions({ stopLineTokenizationAfter: stopLineTokenizationAfter, longLineBoundary: toInteger(opts.longLineBoundary), - + lineHeight: fontInfo.lineHeight, // todo -> duplicated in styling + readOnly: readOnly, + wordSeparators: String(opts.wordSeparators), autoClosingBrackets: toBoolean(opts.autoClosingBrackets), useTabStops: toBoolean(opts.useTabStops), - trimAutoWhitespace: toBoolean(opts.trimAutoWhitespace), - + tabFocusMode: tabFocusMode, layoutInfo: layoutInfo, fontInfo: fontInfo, viewInfo: viewInfo, wrappingInfo: wrappingInfo, contribInfo: contribInfo, - - lineHeight: fontInfo.lineHeight, // todo -> duplicated in styling - }; + }); } private static _sanitizeScrollbarOpts(raw:editorCommon.IEditorScrollbarOptions, mouseWheelScrollSensitivity:number): editorCommon.InternalEditorScrollbarOptions { @@ -298,30 +252,6 @@ class InternalEditorOptionsHelper { mouseWheelScrollSensitivity: mouseWheelScrollSensitivity }); } - - public static createConfigurationChangedEvent(prevOpts:InternalEditorOptions, newOpts:InternalEditorOptions): editorCommon.IConfigurationChangedEvent { - return { - wordSeparators: (prevOpts.wordSeparators !== newOpts.wordSeparators), - - theme: (prevOpts.theme !== newOpts.theme), - readOnly: (prevOpts.readOnly !== newOpts.readOnly), - fontLigatures: (prevOpts.fontLigatures !== newOpts.fontLigatures), - tabFocusMode: (prevOpts.tabFocusMode !== newOpts.tabFocusMode), - stopLineTokenizationAfter: (prevOpts.stopLineTokenizationAfter !== newOpts.stopLineTokenizationAfter), - longLineBoundary: (prevOpts.longLineBoundary !== newOpts.longLineBoundary), - - autoClosingBrackets: (prevOpts.autoClosingBrackets !== newOpts.autoClosingBrackets), - useTabStops: (prevOpts.useTabStops !== newOpts.useTabStops), - trimAutoWhitespace: (prevOpts.trimAutoWhitespace !== newOpts.trimAutoWhitespace), - - layoutInfo: (!prevOpts.layoutInfo.equals(newOpts.layoutInfo)), - fontInfo: (!prevOpts.fontInfo.equals(newOpts.fontInfo)), - viewInfo: prevOpts.viewInfo.createChangeEvent(newOpts.viewInfo), - wrappingInfo: (!prevOpts.wrappingInfo.equals(newOpts.wrappingInfo)), - contribInfo: (!prevOpts.contribInfo.equals(newOpts.contribInfo)), - lineHeight: (prevOpts.lineHeight !== newOpts.lineHeight), - }; - } } function toBoolean(value:any): boolean { @@ -412,8 +342,8 @@ export interface IElementSizeObserver { export abstract class CommonEditorConfiguration extends Disposable implements editorCommon.IConfiguration { - public editor:InternalEditorOptions; - public editorClone:InternalEditorOptions; + public editor:editorCommon.InternalEditorOptions; + public editorClone:editorCommon.InternalEditorOptions; protected _configWithDefaults:ConfigurationWithDefaults; protected _elementSizeObserver: IElementSizeObserver; @@ -429,9 +359,8 @@ export abstract class CommonEditorConfiguration extends Disposable implements ed this._elementSizeObserver = elementSizeObserver; this._isDominatedByLongLines = false; this._lineCount = 1; - this.editor = this._computeInternalOptions(); - this.editorClone = new InternalEditorOptions(this.editor); + this.editorClone = this.editor.clone(); } public dispose(): void { @@ -439,41 +368,25 @@ export abstract class CommonEditorConfiguration extends Disposable implements ed } protected _recomputeOptions(): void { - let oldOpts = this.editor; - this.editor = this._computeInternalOptions(); - this.editorClone = new InternalEditorOptions(this.editor); + this._setOptions(this._computeInternalOptions()); + } - let changeEvent = InternalEditorOptionsHelper.createConfigurationChangedEvent(oldOpts, this.editor); - - let hasChanged = false; - let keys = Object.keys(changeEvent); - for (let i = 0, len = keys.length; i < len; i++) { - let key = keys[i]; - if (changeEvent[key] === true) { - hasChanged = true; - break; - } + private _setOptions(newOptions:editorCommon.InternalEditorOptions): void { + if (this.editor && this.editor.equals(newOptions)) { + return; } - keys = Object.keys(changeEvent.viewInfo); - for (let i = 0, len = keys.length; i < len; i++) { - let key = keys[i]; - if (changeEvent[key] === true) { - hasChanged = true; - break; - } - } - - if (hasChanged) { - this._onDidChange.fire(changeEvent); - } + let changeEvent = this.editor.createChangeEvent(newOptions); + this.editor = newOptions; + this.editorClone = this.editor.clone(); + this._onDidChange.fire(changeEvent); } public getRawOptions(): editorCommon.IEditorOptions { return this._configWithDefaults.getEditorOptions(); } - private _computeInternalOptions(): InternalEditorOptions { + private _computeInternalOptions(): editorCommon.InternalEditorOptions { let opts = this._configWithDefaults.getEditorOptions(); let editorClassName = this._getEditorClassName(opts.theme, toBoolean(opts.fontLigatures)); @@ -485,7 +398,7 @@ export abstract class CommonEditorConfiguration extends Disposable implements ed lineHeight = Math.round(GOLDEN_LINE_HEIGHT_RATIO * fontSize); } - let result = InternalEditorOptionsHelper.createInternalEditorOptions( + return InternalEditorOptionsHelper.createInternalEditorOptions( this.getOuterWidth(), this.getOuterHeight(), opts, @@ -498,8 +411,6 @@ export abstract class CommonEditorConfiguration extends Disposable implements ed this._isDominatedByLongLines, this._lineCount ); - - return new InternalEditorOptions(result); } public updateOptions(newOptions:editorCommon.IEditorOptions): void { @@ -764,7 +675,7 @@ let editorConfiguration:IConfigurationNode = { }, 'editor.trimAutoWhitespace' : { 'type': 'boolean', - 'default': DefaultConfig.editor.trimAutoWhitespace, + 'default': DEFAULT_TRIM_AUTO_WHITESPACE, 'description': nls.localize('trimAutoWhitespace', "Remove trailing auto inserted whitespace") }, 'editor.dismissPeekOnEsc' : { diff --git a/src/vs/editor/common/config/defaultConfig.ts b/src/vs/editor/common/config/defaultConfig.ts index a7dbd770e60..1ec57e58ad5 100644 --- a/src/vs/editor/common/config/defaultConfig.ts +++ b/src/vs/editor/common/config/defaultConfig.ts @@ -18,6 +18,7 @@ export const DEFAULT_INDENTATION = { insertSpaces: true, detectIndentation: true }; +export const DEFAULT_TRIM_AUTO_WHITESPACE = true; const DEFAULT_WINDOWS_FONT_FAMILY = 'Consolas, \'Courier New\', monospace'; const DEFAULT_MAC_FONT_FAMILY = 'Menlo, Monaco, \'Courier New\', monospace'; @@ -90,7 +91,6 @@ class ConfigClass implements IConfiguration { renderWhitespace: false, indentGuides: false, useTabStops: true, - trimAutoWhitespace: true, fontFamily: ( platform.isMacintosh ? DEFAULT_MAC_FONT_FAMILY : (platform.isLinux ? DEFAULT_LINUX_FONT_FAMILY : DEFAULT_WINDOWS_FONT_FAMILY) diff --git a/src/vs/editor/common/editorCommon.ts b/src/vs/editor/common/editorCommon.ts index 059dc2824ca..862e32f4110 100644 --- a/src/vs/editor/common/editorCommon.ts +++ b/src/vs/editor/common/editorCommon.ts @@ -400,7 +400,6 @@ export interface IEditorOptions { */ wordWrapBreakObtrusiveCharacters?: string; -// autoSize?:boolean; /** * Control what pressing Tab does. * If it is false, pressing Tab or Shift-Tab will be handled by the editor. @@ -511,10 +510,6 @@ export interface IEditorOptions { * Inserting and deleting whitespace follows tab stops. */ useTabStops?: boolean; - /** - * Remove trailing auto inserted whitespace. - */ - trimAutoWhitespace?: boolean; /** * The font family */ @@ -666,6 +661,7 @@ export class EditorWrappingInfo { export class InternalEditorViewOptions { _internalEditorViewOptionsBrand: void; + theme:string; experimentalScreenReader: boolean; rulers: number[]; ariaLabel: string; @@ -686,6 +682,7 @@ export class InternalEditorViewOptions { scrollbar:InternalEditorScrollbarOptions; constructor(source:{ + theme:string; experimentalScreenReader: boolean; rulers: number[]; ariaLabel: string; @@ -705,6 +702,7 @@ export class InternalEditorViewOptions { indentGuides: boolean; scrollbar:InternalEditorScrollbarOptions; }) { + this.theme = String(source.theme); this.experimentalScreenReader = Boolean(source.experimentalScreenReader); this.rulers = InternalEditorViewOptions._toSortedIntegerArray(source.rulers); this.ariaLabel = String(source.ariaLabel); @@ -755,7 +753,8 @@ export class InternalEditorViewOptions { public equals(other:InternalEditorViewOptions): boolean { return ( - this.experimentalScreenReader === other.experimentalScreenReader + this.theme === other.theme + && this.experimentalScreenReader === other.experimentalScreenReader && InternalEditorViewOptions._numberArraysEqual(this.rulers, other.rulers) && this.ariaLabel === other.ariaLabel && this.lineNumbers === other.lineNumbers @@ -778,6 +777,7 @@ export class InternalEditorViewOptions { public createChangeEvent(newOpts:InternalEditorViewOptions): IViewConfigurationChangedEvent { return { + theme: this.theme !== newOpts.theme, experimentalScreenReader: this.experimentalScreenReader !== newOpts.experimentalScreenReader, rulers: (!InternalEditorViewOptions._numberArraysEqual(this.rulers, newOpts.rulers)), ariaLabel: this.ariaLabel !== newOpts.ariaLabel, @@ -805,6 +805,7 @@ export class InternalEditorViewOptions { } export interface IViewConfigurationChangedEvent { + theme: boolean; experimentalScreenReader: boolean; rulers: boolean; ariaLabel: boolean; @@ -896,64 +897,114 @@ export class EditorContribOptions { /** * Internal configuration options (transformed or computed) for the editor. */ -export interface IInternalEditorOptions { - readOnly:boolean; +export class InternalEditorOptions { + _internalEditorOptionsBrand: void; + stopLineTokenizationAfter:number; // todo: move to model opts + longLineBoundary:number; // todo: move to model opts + lineHeight:number; // todo: move to fontInfo + + readOnly:boolean; // ---- cursor options wordSeparators: string; autoClosingBrackets:boolean; useTabStops: boolean; tabFocusMode:boolean; - - // ---- model options - trimAutoWhitespace: boolean; - stopLineTokenizationAfter:number; - longLineBoundary:number; - - // ---- Options that are transparent - get no massaging - theme:string; // todo: move to viewInfo - fontLigatures:boolean; // todo: move to fontInfo - - // ---- Options that are computed - + // ---- grouped options layoutInfo: EditorLayoutInfo; fontInfo: FontInfo; viewInfo: InternalEditorViewOptions; wrappingInfo: EditorWrappingInfo; contribInfo: EditorContribOptions; - /** - * Computed line height (deduced from theme and CSS) in px. - */ - lineHeight:number; // todo: move to fontInfo + constructor(source: { + stopLineTokenizationAfter:number; + longLineBoundary:number; + lineHeight:number; + readOnly:boolean; + wordSeparators: string; + autoClosingBrackets:boolean; + useTabStops: boolean; + tabFocusMode:boolean; + layoutInfo: EditorLayoutInfo; + fontInfo: FontInfo; + viewInfo: InternalEditorViewOptions; + wrappingInfo: EditorWrappingInfo; + contribInfo: EditorContribOptions; + }) { + this.stopLineTokenizationAfter = source.stopLineTokenizationAfter|0; + this.longLineBoundary = source.longLineBoundary|0; + this.lineHeight = source.lineHeight|0; + this.readOnly = Boolean(source.readOnly); + this.wordSeparators = String(source.wordSeparators); + this.autoClosingBrackets = Boolean(source.autoClosingBrackets); + this.useTabStops = Boolean(source.useTabStops); + this.tabFocusMode = Boolean(source.tabFocusMode); + this.layoutInfo = source.layoutInfo.clone(); + this.fontInfo = source.fontInfo.clone(); + this.viewInfo = source.viewInfo.clone(); + this.wrappingInfo = source.wrappingInfo.clone(); + this.contribInfo = source.contribInfo.clone(); + } + + public equals(other:InternalEditorOptions): boolean { + return ( + this.stopLineTokenizationAfter === other.stopLineTokenizationAfter + && this.longLineBoundary === other.longLineBoundary + && this.lineHeight === other.lineHeight + && this.readOnly === other.readOnly + && this.wordSeparators === other.wordSeparators + && this.autoClosingBrackets === other.autoClosingBrackets + && this.useTabStops === other.useTabStops + && this.tabFocusMode === other.tabFocusMode + && this.layoutInfo.equals(other.layoutInfo) + && this.fontInfo.equals(other.fontInfo) + && this.viewInfo.equals(other.viewInfo) + && this.wrappingInfo.equals(other.wrappingInfo) + && this.contribInfo.equals(other.contribInfo) + ); + } + + public createChangeEvent(newOpts:InternalEditorOptions): IConfigurationChangedEvent { + return { + stopLineTokenizationAfter: (this.stopLineTokenizationAfter !== newOpts.stopLineTokenizationAfter), + longLineBoundary: (this.longLineBoundary !== newOpts.longLineBoundary), + lineHeight: (this.lineHeight !== newOpts.lineHeight), + readOnly: (this.readOnly !== newOpts.readOnly), + wordSeparators: (this.wordSeparators !== newOpts.wordSeparators), + autoClosingBrackets: (this.autoClosingBrackets !== newOpts.autoClosingBrackets), + useTabStops: (this.useTabStops !== newOpts.useTabStops), + tabFocusMode: (this.tabFocusMode !== newOpts.tabFocusMode), + layoutInfo: (!this.layoutInfo.equals(newOpts.layoutInfo)), + fontInfo: (!this.fontInfo.equals(newOpts.fontInfo)), + viewInfo: this.viewInfo.createChangeEvent(newOpts.viewInfo), + wrappingInfo: (!this.wrappingInfo.equals(newOpts.wrappingInfo)), + contribInfo: (!this.contribInfo.equals(newOpts.contribInfo)), + }; + } + + public clone(): InternalEditorOptions { + return new InternalEditorOptions(this); + } } /** * An event describing that the configuration of the editor has changed. */ export interface IConfigurationChangedEvent { - wordSeparators: boolean; - - // ---- Options that are transparent - get no massaging - theme: boolean; - readOnly: boolean; - fontLigatures: boolean; - tabFocusMode: boolean; stopLineTokenizationAfter: boolean; longLineBoundary: boolean; - - // ---- Options that are transparent - get no massaging + lineHeight: boolean; + readOnly: boolean; + wordSeparators: boolean; autoClosingBrackets: boolean; useTabStops: boolean; - trimAutoWhitespace: boolean; - - // ---- Options that are computed + tabFocusMode: boolean; layoutInfo: boolean; fontInfo: boolean; viewInfo: IViewConfigurationChangedEvent; wrappingInfo: boolean; contribInfo: boolean; - lineHeight: boolean; } /** @@ -2789,7 +2840,7 @@ export class FontInfo extends BareFontInfo { export interface IConfiguration { onDidChange: Event; - editor:IInternalEditorOptions; + editor:InternalEditorOptions; setLineCount(lineCount:number): void; } @@ -3314,7 +3365,7 @@ export interface ICommonCodeEditor extends IEditor { /** * Returns the current editor's configuration */ - getConfiguration(): IInternalEditorOptions; + getConfiguration(): InternalEditorOptions; /** * Returns the 'raw' editor's configuration, as it was applied over the defaults, but without any computed members. diff --git a/src/vs/editor/common/model/textModel.ts b/src/vs/editor/common/model/textModel.ts index 2bfeb1e1a25..10d62317961 100644 --- a/src/vs/editor/common/model/textModel.ts +++ b/src/vs/editor/common/model/textModel.ts @@ -11,7 +11,7 @@ import {Range} from 'vs/editor/common/core/range'; import * as editorCommon from 'vs/editor/common/editorCommon'; import {ModelLine} from 'vs/editor/common/model/modelLine'; import {guessIndentation} from 'vs/editor/common/model/indentationGuesser'; -import {DEFAULT_INDENTATION, DefaultConfig} from 'vs/editor/common/config/defaultConfig'; +import {DEFAULT_INDENTATION, DEFAULT_TRIM_AUTO_WHITESPACE} from 'vs/editor/common/config/defaultConfig'; var LIMIT_FIND_COUNT = 999; @@ -21,7 +21,7 @@ export class TextModel extends OrderGuaranteeEventEmitter implements editorCommo tabSize: DEFAULT_INDENTATION.tabSize, insertSpaces: DEFAULT_INDENTATION.insertSpaces, detectIndentation: false, - trimAutoWhitespace: DefaultConfig.editor.trimAutoWhitespace, + trimAutoWhitespace: DEFAULT_TRIM_AUTO_WHITESPACE, defaultEOL: editorCommon.DefaultEndOfLine.LF }; diff --git a/src/vs/editor/common/services/modelServiceImpl.ts b/src/vs/editor/common/services/modelServiceImpl.ts index ffee163b5fa..c5f868bcb44 100644 --- a/src/vs/editor/common/services/modelServiceImpl.ts +++ b/src/vs/editor/common/services/modelServiceImpl.ts @@ -26,7 +26,7 @@ import {IModelService} from 'vs/editor/common/services/modelService'; import {IResourceService} from 'vs/editor/common/services/resourceService'; import * as platform from 'vs/base/common/platform'; import {IConfigurationService} from 'vs/platform/configuration/common/configuration'; -import {DEFAULT_INDENTATION, DefaultConfig} from 'vs/editor/common/config/defaultConfig'; +import {DEFAULT_INDENTATION, DEFAULT_TRIM_AUTO_WHITESPACE} from 'vs/editor/common/config/defaultConfig'; import {IMessageService} from 'vs/platform/message/common/message'; export interface IRawModelData { @@ -221,7 +221,7 @@ export class ModelServiceImpl implements IModelService { insertSpaces: DEFAULT_INDENTATION.insertSpaces, detectIndentation: DEFAULT_INDENTATION.detectIndentation, defaultEOL: (platform.isLinux || platform.isMacintosh) ? editorCommon.DefaultEndOfLine.LF : editorCommon.DefaultEndOfLine.CRLF, - trimAutoWhitespace: DefaultConfig.editor.trimAutoWhitespace + trimAutoWhitespace: DEFAULT_TRIM_AUTO_WHITESPACE }; this._threadService = threadService; this._markerService = markerService; From 1547d80bc40c94cf91a9c1394f747df3f0ce3ef6 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 6 May 2016 15:55:43 +0200 Subject: [PATCH 093/297] Remove more editor options --- src/vs/editor/common/commonCodeEditor.ts | 3 +- .../common/config/commonEditorConfig.ts | 11 ------ src/vs/editor/common/config/defaultConfig.ts | 3 -- src/vs/editor/common/editorCommon.ts | 38 ++----------------- src/vs/editor/common/model/textModel.ts | 7 ++-- .../common/model/textModelWithTokens.ts | 16 +------- 6 files changed, 10 insertions(+), 68 deletions(-) diff --git a/src/vs/editor/common/commonCodeEditor.ts b/src/vs/editor/common/commonCodeEditor.ts index 89bb026ee85..418d762984d 100644 --- a/src/vs/editor/common/commonCodeEditor.ts +++ b/src/vs/editor/common/commonCodeEditor.ts @@ -669,8 +669,7 @@ export abstract class CommonCodeEditor extends EventEmitter implements IActionPr if (this.model) { this.domElement.setAttribute('data-mode-id', this.model.getMode().getId()); this._langIdKey.set(this.model.getMode().getId()); - this.model.setStopLineTokenizationAfter(this._configuration.editor.stopLineTokenizationAfter); - this._configuration.setIsDominatedByLongLines(this.model.isDominatedByLongLines(this._configuration.editor.longLineBoundary)); + this._configuration.setIsDominatedByLongLines(this.model.isDominatedByLongLines()); this.model.onBeforeAttached(); diff --git a/src/vs/editor/common/config/commonEditorConfig.ts b/src/vs/editor/common/config/commonEditorConfig.ts index b83f7e5f8d8..51510f48fe3 100644 --- a/src/vs/editor/common/config/commonEditorConfig.ts +++ b/src/vs/editor/common/config/commonEditorConfig.ts @@ -78,15 +78,6 @@ class InternalEditorOptionsHelper { let wrappingColumn = toInteger(opts.wrappingColumn, -1); - let stopLineTokenizationAfter:number; - if (typeof opts.stopLineTokenizationAfter !== 'undefined') { - stopLineTokenizationAfter = toInteger(opts.stopLineTokenizationAfter, -1); - } else if (wrappingColumn >= 0) { - stopLineTokenizationAfter = -1; - } else { - stopLineTokenizationAfter = 10000; - } - let stopRenderingLineAfter:number; if (typeof opts.stopRenderingLineAfter !== 'undefined') { stopRenderingLineAfter = toInteger(opts.stopRenderingLineAfter, -1); @@ -201,8 +192,6 @@ class InternalEditorOptionsHelper { }); return new editorCommon.InternalEditorOptions({ - stopLineTokenizationAfter: stopLineTokenizationAfter, - longLineBoundary: toInteger(opts.longLineBoundary), lineHeight: fontInfo.lineHeight, // todo -> duplicated in styling readOnly: readOnly, wordSeparators: String(opts.wordSeparators), diff --git a/src/vs/editor/common/config/defaultConfig.ts b/src/vs/editor/common/config/defaultConfig.ts index 1ec57e58ad5..82d4449acf4 100644 --- a/src/vs/editor/common/config/defaultConfig.ts +++ b/src/vs/editor/common/config/defaultConfig.ts @@ -69,9 +69,6 @@ class ConfigClass implements IConfiguration { wordWrapBreakAfterCharacters: ' \t})]?|&,;¢°′″‰℃、。。、¢,.:;?!%・・ゝゞヽヾーァィゥェォッャュョヮヵヶぁぃぅぇぉっゃゅょゎゕゖㇰㇱㇲㇳㇴㇵㇶㇷㇸㇹㇺㇻㇼㇽㇾㇿ々〻ァィゥェォャュョッー’”〉》」』】〕)]}」', wordWrapBreakObtrusiveCharacters: '.', tabFocusMode: false, - // stopLineTokenizationAfter - // stopRenderingLineAfter - longLineBoundary: 300, // Features hover: true, diff --git a/src/vs/editor/common/editorCommon.ts b/src/vs/editor/common/editorCommon.ts index 862e32f4110..efc31e8cbab 100644 --- a/src/vs/editor/common/editorCommon.ts +++ b/src/vs/editor/common/editorCommon.ts @@ -408,24 +408,12 @@ export interface IEditorOptions { */ tabFocusMode?:boolean; - /** - * Performance guard: Stop tokenizing a line after x characters. - * Defaults to 10000 if wrappingColumn is -1. Defaults to -1 if wrappingColumn is >= 0. - * Use -1 to never stop tokenization. - */ - stopLineTokenizationAfter?:number; /** * Performance guard: Stop rendering a line after x characters. * Defaults to 10000 if wrappingColumn is -1. Defaults to -1 if wrappingColumn is >= 0. * Use -1 to never stop rendering */ stopRenderingLineAfter?:number; - /** - * Performance guard: Force viewport width wrapping if more than half of the - * characters in a model are on lines of length >= `longLineBoundary`. - * Defaults to 300. - */ - longLineBoundary?:number; /** * Enable hover. * Defaults to true. @@ -900,8 +888,6 @@ export class EditorContribOptions { export class InternalEditorOptions { _internalEditorOptionsBrand: void; - stopLineTokenizationAfter:number; // todo: move to model opts - longLineBoundary:number; // todo: move to model opts lineHeight:number; // todo: move to fontInfo readOnly:boolean; @@ -918,8 +904,6 @@ export class InternalEditorOptions { contribInfo: EditorContribOptions; constructor(source: { - stopLineTokenizationAfter:number; - longLineBoundary:number; lineHeight:number; readOnly:boolean; wordSeparators: string; @@ -932,8 +916,6 @@ export class InternalEditorOptions { wrappingInfo: EditorWrappingInfo; contribInfo: EditorContribOptions; }) { - this.stopLineTokenizationAfter = source.stopLineTokenizationAfter|0; - this.longLineBoundary = source.longLineBoundary|0; this.lineHeight = source.lineHeight|0; this.readOnly = Boolean(source.readOnly); this.wordSeparators = String(source.wordSeparators); @@ -949,9 +931,7 @@ export class InternalEditorOptions { public equals(other:InternalEditorOptions): boolean { return ( - this.stopLineTokenizationAfter === other.stopLineTokenizationAfter - && this.longLineBoundary === other.longLineBoundary - && this.lineHeight === other.lineHeight + this.lineHeight === other.lineHeight && this.readOnly === other.readOnly && this.wordSeparators === other.wordSeparators && this.autoClosingBrackets === other.autoClosingBrackets @@ -967,8 +947,6 @@ export class InternalEditorOptions { public createChangeEvent(newOpts:InternalEditorOptions): IConfigurationChangedEvent { return { - stopLineTokenizationAfter: (this.stopLineTokenizationAfter !== newOpts.stopLineTokenizationAfter), - longLineBoundary: (this.longLineBoundary !== newOpts.longLineBoundary), lineHeight: (this.lineHeight !== newOpts.lineHeight), readOnly: (this.readOnly !== newOpts.readOnly), wordSeparators: (this.wordSeparators !== newOpts.wordSeparators), @@ -992,8 +970,6 @@ export class InternalEditorOptions { * An event describing that the configuration of the editor has changed. */ export interface IConfigurationChangedEvent { - stopLineTokenizationAfter: boolean; - longLineBoundary: boolean; lineHeight: boolean; readOnly: boolean; wordSeparators: boolean; @@ -1546,11 +1522,11 @@ export interface ITextModel { /** * Splits characters in two buckets. First bucket (A) is of characters that - * sit in lines with length < `longLineBoundary`. Second bucket (B) is of - * characters that sit in lines with length >= `longLineBoundary`. + * sit in lines with length < `LONG_LINE_BOUNDARY`. Second bucket (B) is of + * characters that sit in lines with length >= `LONG_LINE_BOUNDARY`. * If count(B) > count(A) return true. Returns false otherwise. */ - isDominatedByLongLines(longLineBoundary:number): boolean; + isDominatedByLongLines(): boolean; /** * Get the number of lines in the model. @@ -1650,12 +1626,6 @@ export interface IFoundBracket { */ export interface ITokenizedModel extends ITextModel { - /** - * Set the value at which to stop tokenization. - * The default is 10000. - */ - setStopLineTokenizationAfter(stopLineTokenizationAfter:number): void; - /** * Tokenize if necessary and get the tokens for the line `lineNumber`. * @param lineNumber The line number diff --git a/src/vs/editor/common/model/textModel.ts b/src/vs/editor/common/model/textModel.ts index 10d62317961..e402fbd540c 100644 --- a/src/vs/editor/common/model/textModel.ts +++ b/src/vs/editor/common/model/textModel.ts @@ -14,6 +14,7 @@ import {guessIndentation} from 'vs/editor/common/model/indentationGuesser'; import {DEFAULT_INDENTATION, DEFAULT_TRIM_AUTO_WHITESPACE} from 'vs/editor/common/config/defaultConfig'; var LIMIT_FIND_COUNT = 999; +export const LONG_LINE_BOUNDARY = 1000; export class TextModel extends OrderGuaranteeEventEmitter implements editorCommon.ITextModel { @@ -21,8 +22,8 @@ export class TextModel extends OrderGuaranteeEventEmitter implements editorCommo tabSize: DEFAULT_INDENTATION.tabSize, insertSpaces: DEFAULT_INDENTATION.insertSpaces, detectIndentation: false, + defaultEOL: editorCommon.DefaultEndOfLine.LF, trimAutoWhitespace: DEFAULT_TRIM_AUTO_WHITESPACE, - defaultEOL: editorCommon.DefaultEndOfLine.LF }; _lines:ModelLine[]; @@ -382,7 +383,7 @@ export class TextModel extends OrderGuaranteeEventEmitter implements editorCommo return result; } - public isDominatedByLongLines(longLineBoundary:number): boolean { + public isDominatedByLongLines(): boolean { var smallLineCharCount = 0, longLineCharCount = 0, i: number, @@ -392,7 +393,7 @@ export class TextModel extends OrderGuaranteeEventEmitter implements editorCommo for (i = 0, len = this._lines.length; i < len; i++) { lineLength = lines[i].text.length; - if (lineLength >= longLineBoundary) { + if (lineLength >= LONG_LINE_BOUNDARY) { longLineCharCount += lineLength; } else { smallLineCharCount += lineLength; diff --git a/src/vs/editor/common/model/textModelWithTokens.ts b/src/vs/editor/common/model/textModelWithTokens.ts index a443fe81d6d..5a94dd77610 100644 --- a/src/vs/editor/common/model/textModelWithTokens.ts +++ b/src/vs/editor/common/model/textModelWithTokens.ts @@ -11,7 +11,6 @@ import {IDisposable, dispose} from 'vs/base/common/lifecycle'; import {StopWatch} from 'vs/base/common/stopwatch'; import * as timer from 'vs/base/common/timer'; import {TPromise} from 'vs/base/common/winjs.base'; -import {DefaultConfig} from 'vs/editor/common/config/defaultConfig'; import {Range} from 'vs/editor/common/core/range'; import * as editorCommon from 'vs/editor/common/editorCommon'; import {ModelLine} from 'vs/editor/common/model/modelLine'; @@ -178,7 +177,6 @@ export class TextModelWithTokens extends TextModel implements editorCommon.IToke private _modeListener: IDisposable; private _modeToModelBinder:ModeToModelBinder; private _tokensInflatorMap:TokensInflatorMap; - private _stopLineTokenizationAfter:number; private _invalidLineStartIndex:number; private _lastState:IState; @@ -201,7 +199,6 @@ export class TextModelWithTokens extends TextModel implements editorCommon.IToke this._modeListener = null; this._modeToModelBinder = null; this._tokensInflatorMap = null; - this._stopLineTokenizationAfter = DefaultConfig.editor.stopLineTokenizationAfter; this._invalidLineStartIndex = 0; this._lastState = null; @@ -404,10 +401,6 @@ export class TextModelWithTokens extends TextModel implements editorCommon.IToke this._beginBackgroundTokenization(); } - public setStopLineTokenizationAfter(stopLineTokenizationAfter:number): void { - this._stopLineTokenizationAfter = stopLineTokenizationAfter; - } - public getLineTokens(lineNumber:number, inaccurateTokensAcceptable:boolean = false): editorCommon.ILineTokens { if (lineNumber < 1 || lineNumber > this.getLineCount()) { throw new Error('Illegal value ' + lineNumber + ' for `lineNumber`'); @@ -589,7 +582,6 @@ export class TextModelWithTokens extends TextModel implements editorCommon.IToke tokenizedChars = 0, currentCharsToTokenize = 0, currentEstimatedTimeToTokenize = 0, - stopLineTokenizationAfter = this._stopLineTokenizationAfter, sw = StopWatch.create(false), elapsedTime: number; @@ -607,9 +599,6 @@ export class TextModelWithTokens extends TextModel implements editorCommon.IToke // Compute how many characters will be tokenized for this line currentCharsToTokenize = this._lines[lineNumber - 1].text.length; - if (stopLineTokenizationAfter !== -1 && currentCharsToTokenize > stopLineTokenizationAfter) { - currentCharsToTokenize = stopLineTokenizationAfter; - } if (tokenizedChars > 0) { // If we have enough history, estimate how long tokenizing this line would take @@ -659,10 +648,7 @@ export class TextModelWithTokens extends TextModel implements editorCommon.IToke private _updateTokensUntilLine(lineNumber:number, emitEvents:boolean): void { var linesLength = this._lines.length; var endLineIndex = lineNumber - 1; - var stopLineTokenizationAfter = this._stopLineTokenizationAfter; - if (stopLineTokenizationAfter === -1) { - stopLineTokenizationAfter = 1000000000; // 1 billion, if a line is so long, you have other trouble :). - } + var stopLineTokenizationAfter = 1000000000; // 1 billion, if a line is so long, you have other trouble :). var fromLineNumber = this._invalidLineStartIndex + 1, toLineNumber = lineNumber; From b894e0aef9d03af46a422111334b768c23ddeb23 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 6 May 2016 16:13:14 +0200 Subject: [PATCH 094/297] refactor ai adapter, make sure dispose flushes all events --- src/vs/base/node/aiAdapter.ts | 212 +++++++++--------- .../test/node/aiAdapter/aiAdapter.test.ts | 12 +- .../telemetry/node/appInsightsAppender.ts | 4 +- .../debug/electron-browser/debugService.ts | 15 +- 4 files changed, 126 insertions(+), 117 deletions(-) diff --git a/src/vs/base/node/aiAdapter.ts b/src/vs/base/node/aiAdapter.ts index 8378aae1e90..5facd711274 100644 --- a/src/vs/base/node/aiAdapter.ts +++ b/src/vs/base/node/aiAdapter.ts @@ -4,10 +4,10 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import types = require('vs/base/common/types'); +import {isObject} from 'vs/base/common/types'; import {safeStringify, mixin} from 'vs/base/common/objects'; - -import appInsights = require('applicationinsights'); +import {TPromise} from 'vs/base/common/winjs.base'; +import * as appInsights from 'applicationinsights'; export interface IAIAdapter { log(eventName: string, data?: any): void; @@ -15,144 +15,148 @@ export interface IAIAdapter { dispose(): void; } +namespace AI { + + let _initialized = false; + + function ensureAIEngineIsInitialized(): void { + if (_initialized === false) { + // we need to pass some fake key, otherwise AI throws an exception + appInsights.setup('2588e01f-f6c9-4cd6-a348-143741f8d702') + .setAutoCollectConsole(false) + .setAutoCollectExceptions(false) + .setAutoCollectPerformance(false) + .setAutoCollectRequests(false); + + _initialized = true; + } + } + + export function getClient(aiKey: string): typeof appInsights.client { + + ensureAIEngineIsInitialized(); + + const client = appInsights.getClient(aiKey); + client.channel.setOfflineMode(true); + client.context.tags[client.context.keys.deviceMachineName] = ''; //prevent App Insights from reporting machine name + if (aiKey.indexOf('AIF-') === 0) { + client.config.endpointUrl = 'https://vortex.data.microsoft.com/collect/v1'; + } + return client; + } +} + +interface Properties { + [key: string]: string; +} + +interface Measurements { + [key: string]: number; +} + export class AIAdapter implements IAIAdapter { - private appInsights: typeof appInsights.client; + private _aiClient: typeof appInsights.client; constructor( - private aiKey: string, - private eventPrefix: string, - /* for test only */ - client?: any, - private additionalDataToLog?: any + private _eventPrefix: string, + private _additionalDataToLog: () => TPromise<{ [key: string]: string | number }>, + clientFactoryOrAiKey: (() => typeof appInsights.client) | string // allow factory function for testing ) { - // for test - if (client) { - this.appInsights = client; - return; + if (!this._additionalDataToLog) { + this._additionalDataToLog = () => TPromise.as(undefined); } - - if (aiKey) { - // if another client is already initialized - if (appInsights.client) { - this.appInsights = appInsights.getClient(aiKey); - // no other way to enable offline mode - this.appInsights.channel.setOfflineMode(true); - - } else { - this.appInsights = appInsights.setup(aiKey) - .setAutoCollectRequests(false) - .setAutoCollectPerformance(false) - .setAutoCollectExceptions(false) - .setOfflineMode(true) - .start() - .client; - } - - - if(aiKey.indexOf('AIF-') === 0) { - this.appInsights.config.endpointUrl = 'https://vortex.data.microsoft.com/collect/v1'; - } - - this.setupAIClient(this.appInsights); + if (typeof clientFactoryOrAiKey === 'string') { + this._aiClient = AI.getClient(clientFactoryOrAiKey); + } else if (typeof clientFactoryOrAiKey === 'function') { + this._aiClient = clientFactoryOrAiKey(); } } - private setupAIClient(client: typeof appInsights.client): void { - //prevent App Insights from reporting machine name - if (client && client.context && - client.context.keys && client.context.tags) { - var machineNameKey = client.context.keys.deviceMachineName; - client.context.tags[machineNameKey] = ''; - } - } + private static _getData(data?: any): { properties: Properties, measurements: Measurements } { - private getData(data?: any): any { - var properties: {[key: string]: string;} = {}; - var measurements: {[key: string]: number;} = {}; + const properties: Properties = Object.create(null); + const measurements: Measurements = Object.create(null); - var event_data = this.flaten(data); - for(var prop in event_data) { + const flat = Object.create(null); + AIAdapter._flaten(data, flat); + + for (let prop in flat) { // enforce property names less than 150 char, take the last 150 char - var propName = prop && prop.length > 150 ? prop.substr( prop.length - 149) : prop; - var property = event_data[prop]; - if (types.isNumber(property)) { - measurements[propName] = property; + prop = prop.length > 150 ? prop.substr(prop.length - 149) : prop; + var value = flat[prop]; - } else if (types.isBoolean(property)) { - measurements[propName] = property ? 1:0; - } else if (types.isString(property)) { - //enforce proeprty value to be less than 1024 char, take the first 1024 char - var propValue = property && property.length > 1024 ? property.substring(0, 1023): property; - properties[propName] = propValue; - } else if (!types.isUndefined(property) && property !== null) { - properties[propName] = property; + if (typeof value === 'number') { + measurements[prop] = value; + + } else if (typeof value === 'boolean') { + measurements[prop] = value ? 1 : 0; + + } else if (typeof value === 'string') { + //enforce property value to be less than 1024 char, take the first 1024 char + properties[prop] = value.substring(0, 1023); + + } else if (typeof value !== 'undefined' && value !== null) { + properties[prop] = value; } } return { - properties: properties, - measurements: measurements + properties, + measurements }; } - private flaten(obj:any, order:number = 0, prefix? : string): any { - var result:{[key:string]: any} = {}; - var properties = obj ? Object.getOwnPropertyNames(obj) : []; - for (var i =0; i < properties.length; i++) { - var item = properties[i]; - var index = prefix ? prefix + item : item; + private static _flaten(obj: any, result: {[key: string]: any }, order: number = 0, prefix?: string): void { + if (!obj) { + return; + } - if (types.isArray(obj[item])) { - try { - result[index] = safeStringify(obj[item]); - } catch (e) { - // workaround for catching the edge case for #18383 - // safe stringfy should never throw circular object exception - result[index] = '[Circular-Array]'; - } - } else if (obj[item] instanceof Date) { - result[index] = ( obj[item]).toISOString(); - } else if (types.isObject(obj[item])) { + for(var item of Object.getOwnPropertyNames(obj)){ + const value = obj[item]; + const index = prefix ? prefix + item : item; + + if (Array.isArray(value)) { + result[index] = safeStringify(value); + + } else if (value instanceof Date) { + // TODO unsure why this is here and not in _getData + result[index] = value.toISOString(); + + } else if (isObject(value)) { if (order < 2) { - var item_result = this.flaten(obj[item], order + 1, index + '.'); - for (var prop in item_result) { - result[prop] = item_result[prop]; - } + AIAdapter._flaten(value, result, order + 1, index + '.'); } else { - try { - result[index] = safeStringify(obj[item]); - } catch (e) { - // workaround for catching the edge case for #18383 - // safe stringfy should never throw circular object exception - result[index] = '[Circular]'; - } + result[index] = safeStringify(value); } } else { - result[index] = obj[item]; + result[index] = value; } } - return result; } public log(eventName: string, data?: any): void { - if (this.additionalDataToLog) { - data = mixin(data, this.additionalDataToLog); - } - var result = this.getData(data); - - if (this.appInsights) { - this.appInsights.trackEvent(this.eventPrefix+'/'+eventName, result.properties, result.measurements); + if (!this._aiClient) { + return; } + this._additionalDataToLog().then(additionalData => { + data = mixin(data, additionalData); + let {properties, measurements} = AIAdapter._getData(data); + this._aiClient.trackEvent(this._eventPrefix + '/' + eventName, properties, measurements); + }, err => { + console.error(err); + }); } public logException(exception: any): void { - if (this.appInsights) { - this.appInsights.trackException(exception); + if (this._aiClient) { + this._aiClient.trackException(exception); } } public dispose(): void { - this.appInsights = null; + this._aiClient.sendPendingData(() => { + // all data flushed + }); } } \ No newline at end of file diff --git a/src/vs/base/test/node/aiAdapter/aiAdapter.test.ts b/src/vs/base/test/node/aiAdapter/aiAdapter.test.ts index ed35c5229ee..414f192c15a 100644 --- a/src/vs/base/test/node/aiAdapter/aiAdapter.test.ts +++ b/src/vs/base/test/node/aiAdapter/aiAdapter.test.ts @@ -21,9 +21,9 @@ class AppInsightsMock { public trackEvent(eventName: string, properties?: { string?: string; }, measurements?: { string?: number; }): void { this.events.push({ - eventName: eventName, - properties: properties, - measurements: measurements + eventName, + properties, + measurements }); } public trackPageView(): void { @@ -33,6 +33,10 @@ class AppInsightsMock { public trackException(exception: any): void { this.exceptions.push(exception); } + + public sendPendingData(callback): void { + // called on dispose + } } suite('AIAdapter', () => { @@ -42,7 +46,7 @@ suite('AIAdapter', () => { setup(() => { appInsightsMock = new AppInsightsMock(); - adapter = new AIAdapter(null, prefix, appInsightsMock); + adapter = new AIAdapter(prefix, undefined, () => appInsightsMock); }); teardown(() => { diff --git a/src/vs/platform/telemetry/node/appInsightsAppender.ts b/src/vs/platform/telemetry/node/appInsightsAppender.ts index 362f03f9bb2..26680b99d7d 100644 --- a/src/vs/platform/telemetry/node/appInsightsAppender.ts +++ b/src/vs/platform/telemetry/node/appInsightsAppender.ts @@ -54,11 +54,11 @@ export class AppInsightsAppender implements ITelemetryAppender { } if (key) { - this.appInsights = new AIAdapter(key, AppInsightsAppender.EVENT_NAME_PREFIX); + this.appInsights = new AIAdapter(AppInsightsAppender.EVENT_NAME_PREFIX, undefined, key); } if (asimovKey) { - this.appInsightsVortex = new AIAdapter(asimovKey, AppInsightsAppender.EVENT_NAME_PREFIX); + this.appInsightsVortex = new AIAdapter(AppInsightsAppender.EVENT_NAME_PREFIX, undefined, asimovKey); } this.loadAddtionaProperties(); diff --git a/src/vs/workbench/parts/debug/electron-browser/debugService.ts b/src/vs/workbench/parts/debug/electron-browser/debugService.ts index 3f1725954c5..f71929dce75 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugService.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugService.ts @@ -541,13 +541,14 @@ export class DebugService implements debug.IDebugService { private doCreateSession(configuration: debug.IConfig, changeViewState: boolean): TPromise { this.setStateAndEmit(debug.State.Initializing); - const key = this.configurationManager.adapter.aiKey; - const telemetryInfo = Object.create(null); - this.telemetryService.getTelemetryInfo().then(info => { - telemetryInfo['common.vscodemachineid'] = info.machineId; - telemetryInfo['common.vscodesessionid'] = info.sessionId; - }, errors.onUnexpectedError); - this.telemetryAdapter = new AIAdapter(key, this.configurationManager.adapter.type, null, telemetryInfo); + this.telemetryAdapter = new AIAdapter(this.configurationManager.adapter.type, () => { + return this.telemetryService.getTelemetryInfo().then(info => { + const telemetryInfo: { [key: string]: string } = Object.create(null); + telemetryInfo['common.vscodemachineid'] = info.machineId; + telemetryInfo['common.vscodesessionid'] = info.sessionId; + return telemetryInfo; + }); + }, this.configurationManager.adapter.aiKey); this.session = this.instantiationService.createInstance(session.RawDebugSession, configuration.debugServer, this.configurationManager.adapter, this.telemetryAdapter); this.registerSessionListeners(); From 6fa73fce2fe5bd5861778e5aad7d9b5cd17a5e9a Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 6 May 2016 16:26:44 +0200 Subject: [PATCH 095/297] add tests for additional properties --- src/vs/base/node/aiAdapter.ts | 10 ++++++---- src/vs/base/test/node/aiAdapter/aiAdapter.test.ts | 15 ++++++++++++++- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/vs/base/node/aiAdapter.ts b/src/vs/base/node/aiAdapter.ts index 5facd711274..850f255ffdb 100644 --- a/src/vs/base/node/aiAdapter.ts +++ b/src/vs/base/node/aiAdapter.ts @@ -60,7 +60,7 @@ export class AIAdapter implements IAIAdapter { constructor( private _eventPrefix: string, - private _additionalDataToLog: () => TPromise<{ [key: string]: string | number }>, + private _additionalDataToLog: () => TPromise<{ [key: string]: any }>, clientFactoryOrAiKey: (() => typeof appInsights.client) | string // allow factory function for testing ) { if (!this._additionalDataToLog) { @@ -140,11 +140,13 @@ export class AIAdapter implements IAIAdapter { return; } this._additionalDataToLog().then(additionalData => { - data = mixin(data, additionalData); + return mixin(data, additionalData); + }, err => { + console.error(err); // ignore? + return data; + }).done(data => { let {properties, measurements} = AIAdapter._getData(data); this._aiClient.trackEvent(this._eventPrefix + '/' + eventName, properties, measurements); - }, err => { - console.error(err); }); } diff --git a/src/vs/base/test/node/aiAdapter/aiAdapter.test.ts b/src/vs/base/test/node/aiAdapter/aiAdapter.test.ts index 414f192c15a..291871b2c36 100644 --- a/src/vs/base/test/node/aiAdapter/aiAdapter.test.ts +++ b/src/vs/base/test/node/aiAdapter/aiAdapter.test.ts @@ -5,7 +5,8 @@ 'use strict'; import * as assert from 'assert'; -import { AIAdapter } from 'vs/base/node/aiAdapter'; +import {TPromise} from 'vs/base/common/winjs.base'; +import {AIAdapter} from 'vs/base/node/aiAdapter'; interface IAppInsightsEvent { eventName: string; @@ -60,6 +61,18 @@ suite('AIAdapter', () => { assert.equal(appInsightsMock.events[0].eventName, `${prefix}/testEvent`); }); + test('addional data', () => { + adapter = new AIAdapter(prefix, () => TPromise.as({ first: '1st', second: 2, third: true }), () => appInsightsMock); + adapter.log('testEvent'); + + assert.equal(appInsightsMock.events.length, 1); + let [first] = appInsightsMock.events; + assert.equal(first.eventName, `${prefix}/testEvent`); + assert.equal(first.properties['first'], '1st'); + assert.equal(first.measurements['second'], '2'); + assert.equal(first.measurements['third'], 1); + }); + test('Track UnhandledError as exception and events', () => { var sampleError = new Error('test'); From 1819da32089a9d1f1663633a9e3193353dccc4d3 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 6 May 2016 16:28:40 +0200 Subject: [PATCH 096/297] remove unused _userIdHash from telemetry --- src/vs/platform/telemetry/browser/telemetryService.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/vs/platform/telemetry/browser/telemetryService.ts b/src/vs/platform/telemetry/browser/telemetryService.ts index 1399a730080..4fe3b6ec036 100644 --- a/src/vs/platform/telemetry/browser/telemetryService.ts +++ b/src/vs/platform/telemetry/browser/telemetryService.ts @@ -49,7 +49,6 @@ export class TelemetryService implements ITelemetryService { private _eventCount = 0; private _startTime = new Date(); private _optInFriendly = ['optInStatus']; //holds a cache of predefined events that can be sent regardress of user optin status - private _userIdHash: string; private _cleanupPatterns: [RegExp, string][]= []; constructor(config?: ITelemetryServiceConfig) { @@ -171,7 +170,6 @@ export class TelemetryService implements ITelemetryService { data['sessionID'] = this._telemetryInfo.sessionId; data['timestamp'] = eventDate; data['version'] = this._configuration.version; - data['userId'] = this._userIdHash; data['commitHash'] = this._configuration.commitHash; data['common.platform'] = Platform.Platform[Platform.platform]; data['common.timesincesessionstart'] = (eventDate.getTime() - this._startTime.getTime()); From 289370f2f335eeb2cd8b74cd8f20101d1ed3335a Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 6 May 2016 17:09:02 +0200 Subject: [PATCH 097/297] Fixes #959: Do not use translate3d when the zoomLevel is not 0 --- src/vs/base/browser/browser.ts | 72 +++++++++---------- .../browser/ui/scrollbar/abstractScrollbar.ts | 5 ++ .../browser/ui/scrollbar/scrollableElement.ts | 7 ++ src/vs/editor/browser/config/configuration.ts | 6 ++ src/vs/editor/browser/view/viewOverlays.ts | 8 ++- .../browser/viewLayout/scrollManager.ts | 6 +- .../browser/viewParts/lines/viewLines.ts | 8 ++- .../overviewRuler/decorationsOverviewRuler.ts | 6 ++ .../viewParts/overviewRuler/overviewRuler.ts | 8 ++- .../overviewRuler/overviewRulerImpl.ts | 15 +++- .../viewParts/viewCursors/viewCursors.ts | 8 ++- .../common/config/commonEditorConfig.ts | 9 ++- src/vs/editor/common/editorCommon.ts | 6 ++ .../test/common/mocks/mockConfiguration.ts | 4 ++ src/vs/workbench/electron-browser/actions.ts | 7 ++ .../workbench/electron-browser/integration.ts | 6 ++ 16 files changed, 126 insertions(+), 55 deletions(-) diff --git a/src/vs/base/browser/browser.ts b/src/vs/base/browser/browser.ts index 166da83e90b..99fda39e773 100644 --- a/src/vs/base/browser/browser.ts +++ b/src/vs/base/browser/browser.ts @@ -6,46 +6,42 @@ import types = require('vs/base/common/types'); import * as Platform from 'vs/base/common/platform'; +import Event, {Emitter} from 'vs/base/common/event'; +import {IDisposable} from 'vs/base/common/lifecycle'; -interface ISafeWindow { - Worker: any; +class ZoomManager { + + public static INSTANCE = new ZoomManager(); + + private _zoomLevel: number = 0; + + private _onDidChangeZoomLevel: Emitter = new Emitter(); + public onDidChangeZoomLevel:Event = this._onDidChangeZoomLevel.event; + public getZoomLevel(): number { + return this._zoomLevel; + } + + public setZoomLevel(zoomLevel:number): void { + if (this._zoomLevel === zoomLevel) { + return; + } + + this._zoomLevel = zoomLevel; + this._onDidChangeZoomLevel.fire(this._zoomLevel); + } } -interface ISafeDocument { - URL: string; - createElement(tagName: 'div'): HTMLDivElement; - createElement(tagName: string): HTMLElement; +export function getZoomLevel(): number { + return ZoomManager.INSTANCE.getZoomLevel(); +} +export function setZoomLevel(zoomLevel:number): void { + ZoomManager.INSTANCE.setZoomLevel(zoomLevel); +} +export function onDidChangeZoomLevel(callback:(zoomLevel:number)=>void): IDisposable { + return ZoomManager.INSTANCE.onDidChangeZoomLevel(callback); } -interface INavigator { - userAgent: string; -} - -interface IGlobalScope { - navigator: INavigator; - document: ISafeDocument; - history: { - pushState: any - }; -} - -const globals = (typeof self === 'object' ? self : global); - -// MAC: -// chrome: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.100 Safari/535.2" -// safari: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2) AppleWebKit/534.51.22 (KHTML, like Gecko) Version/5.1.1 Safari/534.51.22" -// -// WINDOWS: -// chrome: "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.102 Safari/535.2" -// IE: "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; MS-RTC LM 8; InfoPath.3; Zune 4.7)" -// Opera: "Opera/9.80 (Windows NT 6.1; U; en) Presto/2.9.168 Version/11.52" -// FF: "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:8.0) Gecko/20100101 Firefox/8.0" - -// LINUX: -// chrome: "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36" -// firefox: "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:34.0) Gecko/20100101 Firefox/34.0" - -const userAgent = globals.navigator ? globals.navigator.userAgent : ''; +const userAgent = navigator.userAgent; // DOCUMENTED FOR FUTURE REFERENCE: // When running IE11 in IE10 document mode, the code below will identify the browser as being IE10, @@ -76,12 +72,8 @@ export function hasCSSAnimationSupport() { return this._hasCSSAnimationSupport; } - if (!globals.document) { - return false; - } - let supported = false; - let element = globals.document.createElement('div'); + let element = document.createElement('div'); let properties = ['animationName', 'webkitAnimationName', 'msAnimationName', 'MozAnimationName', 'OAnimationName']; for (let i = 0; i < properties.length; i++) { let property = properties[i]; diff --git a/src/vs/base/browser/ui/scrollbar/abstractScrollbar.ts b/src/vs/base/browser/ui/scrollbar/abstractScrollbar.ts index 2a9099717e1..62b1f51d898 100644 --- a/src/vs/base/browser/ui/scrollbar/abstractScrollbar.ts +++ b/src/vs/base/browser/ui/scrollbar/abstractScrollbar.ts @@ -106,6 +106,11 @@ export abstract class AbstractScrollbar extends Widget { // ----------------- Update state + public setCanUseTranslate3d(canUseTranslate3d: boolean): boolean { + this._canUseTranslate3d = canUseTranslate3d; + return true; + } + protected _onElementSize(visibleSize: number): boolean { if (this._scrollbarState.setVisibleSize(visibleSize)) { this._visibilityController.setIsNeeded(this._scrollbarState.isNeeded()); diff --git a/src/vs/base/browser/ui/scrollbar/scrollableElement.ts b/src/vs/base/browser/ui/scrollbar/scrollableElement.ts index 1bd24149f75..dd15d50c379 100644 --- a/src/vs/base/browser/ui/scrollbar/scrollableElement.ts +++ b/src/vs/base/browser/ui/scrollbar/scrollableElement.ts @@ -186,6 +186,13 @@ export class ScrollableElement extends Widget { this._options.handleMouseWheel = massagedOptions.handleMouseWheel; this._options.mouseWheelScrollSensitivity = massagedOptions.mouseWheelScrollSensitivity; this._setListeningToMouseWheel(this._options.handleMouseWheel); + + this._shouldRender = this._horizontalScrollbar.setCanUseTranslate3d(massagedOptions.canUseTranslate3d) || this._shouldRender; + this._shouldRender = this._verticalScrollbar.setCanUseTranslate3d(massagedOptions.canUseTranslate3d) || this._shouldRender; + + if (!this._options.lazyRender) { + this._render(); + } } // -------------------- mouse wheel scrolling -------------------- diff --git a/src/vs/editor/browser/config/configuration.ts b/src/vs/editor/browser/config/configuration.ts index ffdeefebfb4..99f6312815b 100644 --- a/src/vs/editor/browser/config/configuration.ts +++ b/src/vs/editor/browser/config/configuration.ts @@ -241,6 +241,8 @@ export class Configuration extends CommonEditorConfiguration { if (this._configWithDefaults.getEditorOptions().automaticLayout) { this._elementSizeObserver.startObserving(); } + + this._register(browser.onDidChangeZoomLevel(_ => this._recomputeOptions())); } private _onReferenceDomElementSizeChanged(): void { @@ -287,6 +289,10 @@ export class Configuration extends CommonEditorConfiguration { return this._elementSizeObserver.getHeight(); } + protected _getCanUseTranslate3d(): boolean { + return browser.canUseTranslate3d && browser.getZoomLevel() === 0; + } + protected readConfiguration(bareFontInfo:BareFontInfo): FontInfo { return CSSBasedConfiguration.INSTANCE.readConfiguration(bareFontInfo); } diff --git a/src/vs/editor/browser/view/viewOverlays.ts b/src/vs/editor/browser/view/viewOverlays.ts index 4e4959a9c89..b813927ab8b 100644 --- a/src/vs/editor/browser/view/viewOverlays.ts +++ b/src/vs/editor/browser/view/viewOverlays.ts @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import * as browser from 'vs/base/browser/browser'; import {StyleMutator, FastDomNode, createFastDomNode} from 'vs/base/browser/styleMutator'; import {IScrollEvent, IConfigurationChangedEvent, EditorLayoutInfo, IModelDecoration} from 'vs/editor/common/editorCommon'; import * as editorBrowser from 'vs/editor/browser/editorBrowser'; @@ -224,6 +223,7 @@ export class MarginViewOverlays extends ViewOverlays { private _glyphMarginWidth:number; private _scrollHeight:number; private _contentLeft: number; + private _canUseTranslate3d: boolean; constructor(context:ViewContext, layoutProvider:ILayoutProvider) { super(context, layoutProvider); @@ -232,6 +232,7 @@ export class MarginViewOverlays extends ViewOverlays { this._glyphMarginWidth = context.configuration.editor.layoutInfo.glyphMarginWidth; this._scrollHeight = layoutProvider.getScrollHeight(); this._contentLeft = context.configuration.editor.layoutInfo.contentLeft; + this._canUseTranslate3d = context.configuration.editor.viewInfo.canUseTranslate3d; this.domNode.setClassName(editorBrowser.ClassNames.MARGIN_VIEW_OVERLAYS + ' monaco-editor-background'); this.domNode.setWidth(1); @@ -274,13 +275,16 @@ export class MarginViewOverlays extends ViewOverlays { if (e.fontInfo) { Configuration.applyFontInfo(this.domNode, this._context.configuration.editor.fontInfo); } + if (e.viewInfo.canUseTranslate3d) { + this._canUseTranslate3d = this._context.configuration.editor.viewInfo.canUseTranslate3d; + } return super.onConfigurationChanged(e); } _viewOverlaysRender(ctx:IRestrictedRenderingContext): void { super._viewOverlaysRender(ctx); - if (browser.canUseTranslate3d) { + if (this._canUseTranslate3d) { var transform = 'translate3d(0px, ' + ctx.linesViewportData.visibleRangesDeltaTop + 'px, 0px)'; this.domNode.setTransform(transform); this.domNode.setTop(0); diff --git a/src/vs/editor/browser/viewLayout/scrollManager.ts b/src/vs/editor/browser/viewLayout/scrollManager.ts index fed40b8435f..e4585410556 100644 --- a/src/vs/editor/browser/viewLayout/scrollManager.ts +++ b/src/vs/editor/browser/viewLayout/scrollManager.ts @@ -36,7 +36,7 @@ export class ScrollManager implements IDisposable { var configScrollbarOpts = this.configuration.editor.viewInfo.scrollbar; var scrollbarOptions:ScrollableElementCreationOptions = { - canUseTranslate3d: true, + canUseTranslate3d: this.configuration.editor.viewInfo.canUseTranslate3d, listenOnDomNode: viewDomNode, vertical: configScrollbarOpts.vertical, horizontal: configScrollbarOpts.horizontal, @@ -64,9 +64,9 @@ export class ScrollManager implements IDisposable { this.toDispose.push(this.configuration.onDidChange((e:IConfigurationChangedEvent) => { this.scrollbar.updateClassName(ClassNames.SCROLLABLE_ELEMENT + ' ' + this.configuration.editor.viewInfo.theme); - if (e.viewInfo.scrollbar) { + if (e.viewInfo.scrollbar || e.viewInfo.canUseTranslate3d) { let newOpts:ScrollableElementChangeOptions = { - canUseTranslate3d: true, + canUseTranslate3d: this.configuration.editor.viewInfo.canUseTranslate3d, handleMouseWheel: this.configuration.editor.viewInfo.scrollbar.handleMouseWheel, mouseWheelScrollSensitivity: this.configuration.editor.viewInfo.scrollbar.mouseWheelScrollSensitivity }; diff --git a/src/vs/editor/browser/viewParts/lines/viewLines.ts b/src/vs/editor/browser/viewParts/lines/viewLines.ts index 2e38399174e..67e3ae60ad6 100644 --- a/src/vs/editor/browser/viewParts/lines/viewLines.ts +++ b/src/vs/editor/browser/viewParts/lines/viewLines.ts @@ -6,7 +6,6 @@ import 'vs/css!./viewLines'; import {RunOnceScheduler} from 'vs/base/common/async'; -import * as browser from 'vs/base/browser/browser'; import {StyleMutator} from 'vs/base/browser/styleMutator'; import {Range} from 'vs/editor/common/core/range'; import * as editorCommon from 'vs/editor/common/editorCommon'; @@ -65,6 +64,7 @@ export class ViewLines extends ViewLayer { private _lineHeight: number; private _isViewportWrapping: boolean; private _revealHorizontalRightPadding: number; + private _canUseTranslate3d: boolean; // --- width private _maxLineWidth: number; @@ -78,6 +78,7 @@ export class ViewLines extends ViewLayer { this._lineHeight = this._context.configuration.editor.lineHeight; this._isViewportWrapping = this._context.configuration.editor.wrappingInfo.isViewportWrapping; this._revealHorizontalRightPadding = this._context.configuration.editor.viewInfo.revealHorizontalRightPadding; + this._canUseTranslate3d = context.configuration.editor.viewInfo.canUseTranslate3d; this._layoutProvider = layoutProvider; this.domNode.setClassName(ClassNames.VIEW_LINES); Configuration.applyFontInfo(this.domNode, this._context.configuration.editor.fontInfo); @@ -122,6 +123,9 @@ export class ViewLines extends ViewLayer { if (e.viewInfo.revealHorizontalRightPadding) { this._revealHorizontalRightPadding = this._context.configuration.editor.viewInfo.revealHorizontalRightPadding; } + if (e.viewInfo.canUseTranslate3d) { + this._canUseTranslate3d = this._context.configuration.editor.viewInfo.canUseTranslate3d; + } if (e.fontInfo) { Configuration.applyFontInfo(this.domNode, this._context.configuration.editor.fontInfo); } @@ -407,7 +411,7 @@ export class ViewLines extends ViewLayer { } // (4) handle scrolling - if (browser.canUseTranslate3d) { + if (this._canUseTranslate3d) { let transform = 'translate3d(' + -this._layoutProvider.getScrollLeft() + 'px, ' + linesViewportData.visibleRangesDeltaTop + 'px, 0px)'; StyleMutator.setTransform(this.domNode.domNode.parentNode, transform); StyleMutator.setTop(this.domNode.domNode.parentNode, 0); // TODO@Alex diff --git a/src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler.ts b/src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler.ts index 88b7b97b714..463224e6047 100644 --- a/src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler.ts +++ b/src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler.ts @@ -37,6 +37,7 @@ export class DecorationsOverviewRuler extends ViewPart { 'decorationsOverviewRuler', scrollHeight, this._context.configuration.editor.lineHeight, + this._context.configuration.editor.viewInfo.canUseTranslate3d, DecorationsOverviewRuler.DECORATION_HEIGHT, DecorationsOverviewRuler.DECORATION_HEIGHT, getVerticalOffsetForLine @@ -80,6 +81,11 @@ export class DecorationsOverviewRuler extends ViewPart { shouldRender = true; } + if (e.viewInfo.canUseTranslate3d) { + this._overviewRuler.setCanUseTranslate3d(this._context.configuration.editor.viewInfo.canUseTranslate3d, false); + shouldRender = true; + } + if (prevLanesCount !== newLanesCount) { this._overviewRuler.setLanesCount(newLanesCount, false); shouldRender = true; diff --git a/src/vs/editor/browser/viewParts/overviewRuler/overviewRuler.ts b/src/vs/editor/browser/viewParts/overviewRuler/overviewRuler.ts index b40acc4bb36..a14bb490716 100644 --- a/src/vs/editor/browser/viewParts/overviewRuler/overviewRuler.ts +++ b/src/vs/editor/browser/viewParts/overviewRuler/overviewRuler.ts @@ -19,7 +19,7 @@ export class OverviewRuler extends ViewEventHandler implements IOverviewRuler { super(); this._context = context; this._overviewRuler = new OverviewRulerImpl(0, cssClassName, scrollHeight, this._context.configuration.editor.lineHeight, - minimumHeight, maximumHeight, getVerticalOffsetForLine); + this._context.configuration.editor.viewInfo.canUseTranslate3d, minimumHeight, maximumHeight, getVerticalOffsetForLine); this._context.addEventHandler(this); } @@ -38,6 +38,12 @@ export class OverviewRuler extends ViewEventHandler implements IOverviewRuler { this._overviewRuler.setLineHeight(this._context.configuration.editor.lineHeight, true); return true; } + + if (e.viewInfo.canUseTranslate3d) { + this._overviewRuler.setCanUseTranslate3d(this._context.configuration.editor.viewInfo.canUseTranslate3d, true); + return true; + } + return false; } diff --git a/src/vs/editor/browser/viewParts/overviewRuler/overviewRulerImpl.ts b/src/vs/editor/browser/viewParts/overviewRuler/overviewRulerImpl.ts index 131cdb3503f..c0e3c8c4526 100644 --- a/src/vs/editor/browser/viewParts/overviewRuler/overviewRulerImpl.ts +++ b/src/vs/editor/browser/viewParts/overviewRuler/overviewRulerImpl.ts @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import * as browser from 'vs/base/browser/browser'; import {StyleMutator} from 'vs/base/browser/styleMutator'; import {OverviewRulerPosition, OverviewRulerLane} from 'vs/editor/common/editorCommon'; import {OverviewRulerZone, ColorZone} from 'vs/editor/browser/editorBrowser'; @@ -278,8 +277,9 @@ export class OverviewRulerImpl { private _domNode: HTMLCanvasElement; private _lanesCount:number; private _zoneManager: ZoneManager; + private _canUseTranslate3d: boolean; - constructor(canvasLeftOffset:number, cssClassName:string, scrollHeight:number, lineHeight:number, minimumHeight:number, maximumHeight:number, getVerticalOffsetForLine:(lineNumber:number)=>number) { + constructor(canvasLeftOffset:number, cssClassName:string, scrollHeight:number, lineHeight:number, canUseTranslate3d:boolean, minimumHeight:number, maximumHeight:number, getVerticalOffsetForLine:(lineNumber:number)=>number) { this._canvasLeftOffset = canvasLeftOffset; this._domNode = document.createElement('canvas'); @@ -288,6 +288,8 @@ export class OverviewRulerImpl { this._lanesCount = 3; + this._canUseTranslate3d = canUseTranslate3d; + this._zoneManager = new ZoneManager(getVerticalOffsetForLine); this._zoneManager.setMinimumHeight(minimumHeight); this._zoneManager.setMaximumHeight(maximumHeight); @@ -366,6 +368,13 @@ export class OverviewRulerImpl { } } + public setCanUseTranslate3d(canUseTranslate3d:boolean, render:boolean): void { + this._canUseTranslate3d = canUseTranslate3d; + if (render) { + this.render(true); + } + } + public setZones(zones:OverviewRulerZone[], render:boolean): void { this._zoneManager.setZones(zones); if (render) { @@ -380,7 +389,7 @@ export class OverviewRulerImpl { if (this._zoneManager.getOuterHeight() === 0) { return false; } - if (browser.canUseTranslate3d) { + if (this._canUseTranslate3d) { StyleMutator.setTransform(this._domNode, 'translate3d(0px, 0px, 0px)'); } else { StyleMutator.setTransform(this._domNode, ''); diff --git a/src/vs/editor/browser/viewParts/viewCursors/viewCursors.ts b/src/vs/editor/browser/viewParts/viewCursors/viewCursors.ts index 472a2eec8f0..84f0dd5f393 100644 --- a/src/vs/editor/browser/viewParts/viewCursors/viewCursors.ts +++ b/src/vs/editor/browser/viewParts/viewCursors/viewCursors.ts @@ -6,7 +6,6 @@ 'use strict'; import 'vs/css!./viewCursors'; -import * as browser from 'vs/base/browser/browser'; import * as editorCommon from 'vs/editor/common/editorCommon'; import {ClassNames} from 'vs/editor/browser/editorBrowser'; import {ViewPart} from 'vs/editor/browser/view/viewPart'; @@ -28,6 +27,7 @@ export class ViewCursors extends ViewPart { private _readOnly: boolean; private _cursorBlinking: string; private _cursorStyle: editorCommon.TextEditorCursorStyle; + private _canUseTranslate3d: boolean; private _isVisible: boolean; @@ -46,6 +46,7 @@ export class ViewCursors extends ViewPart { this._readOnly = this._context.configuration.editor.readOnly; this._cursorBlinking = this._context.configuration.editor.viewInfo.cursorBlinking; this._cursorStyle = this._context.configuration.editor.viewInfo.cursorStyle; + this._canUseTranslate3d = context.configuration.editor.viewInfo.canUseTranslate3d; this._primaryCursor = new ViewCursor(this._context, false); this._secondaryCursors = []; @@ -152,6 +153,9 @@ export class ViewCursors extends ViewPart { if (e.viewInfo.cursorStyle) { this._cursorStyle = this._context.configuration.editor.viewInfo.cursorStyle; } + if (e.viewInfo.canUseTranslate3d) { + this._canUseTranslate3d = this._context.configuration.editor.viewInfo.canUseTranslate3d; + } this._primaryCursor.onConfigurationChanged(e); this._updateBlinking(); @@ -290,7 +294,7 @@ export class ViewCursors extends ViewPart { this._secondaryCursors[i].render(ctx); } - if (browser.canUseTranslate3d) { + if (this._canUseTranslate3d) { this._domNode.setTransform('translate3d(0px, 0px, 0px)'); } else { this._domNode.setTransform(''); diff --git a/src/vs/editor/common/config/commonEditorConfig.ts b/src/vs/editor/common/config/commonEditorConfig.ts index 51510f48fe3..3022cdf5049 100644 --- a/src/vs/editor/common/config/commonEditorConfig.ts +++ b/src/vs/editor/common/config/commonEditorConfig.ts @@ -73,7 +73,8 @@ class InternalEditorOptionsHelper { fontInfo: editorCommon.FontInfo, editorClassName:string, isDominatedByLongLines:boolean, - lineCount: number + lineCount: number, + canUseTranslate3d: boolean ): editorCommon.InternalEditorOptions { let wrappingColumn = toInteger(opts.wrappingColumn, -1); @@ -155,6 +156,7 @@ class InternalEditorOptionsHelper { let viewInfo = new editorCommon.InternalEditorViewOptions({ theme: opts.theme, + canUseTranslate3d: canUseTranslate3d, experimentalScreenReader: toBoolean(opts.experimentalScreenReader), rulers: toSortedIntegerArray(opts.rulers), ariaLabel: String(opts.ariaLabel), @@ -398,7 +400,8 @@ export abstract class CommonEditorConfiguration extends Disposable implements ed })), editorClassName, this._isDominatedByLongLines, - this._lineCount + this._lineCount, + this._getCanUseTranslate3d() ); } @@ -423,6 +426,8 @@ export abstract class CommonEditorConfiguration extends Disposable implements ed protected abstract getOuterHeight(): number; + protected abstract _getCanUseTranslate3d(): boolean; + protected abstract readConfiguration(styling: editorCommon.BareFontInfo): editorCommon.FontInfo; } diff --git a/src/vs/editor/common/editorCommon.ts b/src/vs/editor/common/editorCommon.ts index efc31e8cbab..6bbb5bbed76 100644 --- a/src/vs/editor/common/editorCommon.ts +++ b/src/vs/editor/common/editorCommon.ts @@ -650,6 +650,7 @@ export class InternalEditorViewOptions { _internalEditorViewOptionsBrand: void; theme:string; + canUseTranslate3d:boolean; experimentalScreenReader: boolean; rulers: number[]; ariaLabel: string; @@ -671,6 +672,7 @@ export class InternalEditorViewOptions { constructor(source:{ theme:string; + canUseTranslate3d:boolean; experimentalScreenReader: boolean; rulers: number[]; ariaLabel: string; @@ -691,6 +693,7 @@ export class InternalEditorViewOptions { scrollbar:InternalEditorScrollbarOptions; }) { this.theme = String(source.theme); + this.canUseTranslate3d = Boolean(source.canUseTranslate3d); this.experimentalScreenReader = Boolean(source.experimentalScreenReader); this.rulers = InternalEditorViewOptions._toSortedIntegerArray(source.rulers); this.ariaLabel = String(source.ariaLabel); @@ -742,6 +745,7 @@ export class InternalEditorViewOptions { public equals(other:InternalEditorViewOptions): boolean { return ( this.theme === other.theme + && this.canUseTranslate3d === other.canUseTranslate3d && this.experimentalScreenReader === other.experimentalScreenReader && InternalEditorViewOptions._numberArraysEqual(this.rulers, other.rulers) && this.ariaLabel === other.ariaLabel @@ -766,6 +770,7 @@ export class InternalEditorViewOptions { public createChangeEvent(newOpts:InternalEditorViewOptions): IViewConfigurationChangedEvent { return { theme: this.theme !== newOpts.theme, + canUseTranslate3d: this.canUseTranslate3d !== newOpts.canUseTranslate3d, experimentalScreenReader: this.experimentalScreenReader !== newOpts.experimentalScreenReader, rulers: (!InternalEditorViewOptions._numberArraysEqual(this.rulers, newOpts.rulers)), ariaLabel: this.ariaLabel !== newOpts.ariaLabel, @@ -794,6 +799,7 @@ export class InternalEditorViewOptions { export interface IViewConfigurationChangedEvent { theme: boolean; + canUseTranslate3d: boolean; experimentalScreenReader: boolean; rulers: boolean; ariaLabel: boolean; diff --git a/src/vs/editor/test/common/mocks/mockConfiguration.ts b/src/vs/editor/test/common/mocks/mockConfiguration.ts index ca45c98bf01..1f026f86eb6 100644 --- a/src/vs/editor/test/common/mocks/mockConfiguration.ts +++ b/src/vs/editor/test/common/mocks/mockConfiguration.ts @@ -25,6 +25,10 @@ export class MockConfiguration extends CommonEditorConfiguration { return 100; } + protected _getCanUseTranslate3d(): boolean { + return true; + } + protected readConfiguration(styling: BareFontInfo): FontInfo { return new FontInfo({ fontFamily: 'mockFont', diff --git a/src/vs/workbench/electron-browser/actions.ts b/src/vs/workbench/electron-browser/actions.ts index 1241720ee14..b6618f88933 100644 --- a/src/vs/workbench/electron-browser/actions.ts +++ b/src/vs/workbench/electron-browser/actions.ts @@ -19,6 +19,7 @@ import {IQuickOpenService} from 'vs/workbench/services/quickopen/common/quickOpe import {IConfigurationService} from 'vs/platform/configuration/common/configuration'; import {KeybindingsRegistry} from 'vs/platform/keybinding/common/keybindingsRegistry'; import {ServicesAccessor} from 'vs/platform/instantiation/common/instantiation'; +import * as browser from 'vs/base/browser/browser'; import {ipcRenderer as ipc, webFrame, remote} from 'electron'; @@ -171,6 +172,8 @@ export class ZoomInAction extends Action { public run(): TPromise { webFrame.setZoomLevel(webFrame.getZoomLevel() + 1); + // Ensure others can listen to zoom level changes + browser.setZoomLevel(webFrame.getZoomLevel()); return TPromise.as(true); } @@ -222,6 +225,8 @@ export class ZoomOutAction extends BaseZoomAction { } webFrame.setZoomLevel(newZoomLevelCandiate); + // Ensure others can listen to zoom level changes + browser.setZoomLevel(webFrame.getZoomLevel()); return TPromise.as(true); } @@ -243,6 +248,8 @@ export class ZoomResetAction extends BaseZoomAction { public run(): TPromise { const level = this.getConfiguredZoomLevel(); webFrame.setZoomLevel(level); + // Ensure others can listen to zoom level changes + browser.setZoomLevel(webFrame.getZoomLevel()); return TPromise.as(true); } diff --git a/src/vs/workbench/electron-browser/integration.ts b/src/vs/workbench/electron-browser/integration.ts index bc93858f66e..73816d82363 100644 --- a/src/vs/workbench/electron-browser/integration.ts +++ b/src/vs/workbench/electron-browser/integration.ts @@ -22,6 +22,7 @@ import {IWorkspaceContextService}from 'vs/workbench/services/workspace/common/co import {IWindowService}from 'vs/workbench/services/window/electron-browser/windowService'; import {IWindowConfiguration} from 'vs/workbench/electron-browser/window'; import {IConfigurationService} from 'vs/platform/configuration/common/configuration'; +import * as browser from 'vs/base/browser/browser'; import win = require('vs/workbench/electron-browser/window'); @@ -116,6 +117,9 @@ export class ElectronIntegration { this.messageService.show(Severity.Info, message); }); + // Ensure others can listen to zoom level changes + browser.setZoomLevel(webFrame.getZoomLevel()); + // Configuration changes let previousConfiguredZoomLevel: number; this.configurationService.onDidUpdateConfiguration(e => { @@ -135,6 +139,8 @@ export class ElectronIntegration { if (webFrame.getZoomLevel() !== newZoomLevel) { webFrame.setZoomLevel(newZoomLevel); + // Ensure others can listen to zoom level changes + browser.setZoomLevel(webFrame.getZoomLevel()); } }); From a5c44d309441aeb79771c0ed07fa6db3b8a90a00 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 6 May 2016 17:29:13 +0200 Subject: [PATCH 098/297] add tests for additional properties in AI appender --- .../telemetry/node/appInsightsAppender.ts | 33 ++++------ .../test/node/appInsightsAppender.test.ts | 61 ++++++++++++------- src/vs/workbench/electron-browser/shell.ts | 2 +- 3 files changed, 52 insertions(+), 44 deletions(-) diff --git a/src/vs/platform/telemetry/node/appInsightsAppender.ts b/src/vs/platform/telemetry/node/appInsightsAppender.ts index 26680b99d7d..e31a974857d 100644 --- a/src/vs/platform/telemetry/node/appInsightsAppender.ts +++ b/src/vs/platform/telemetry/node/appInsightsAppender.ts @@ -7,12 +7,11 @@ import errors = require('vs/base/common/errors'); import {IStorageService} from 'vs/platform/storage/common/storage'; import {ITelemetryAppender} from 'vs/platform/telemetry/common/telemetry'; -import {IEnvironment} from 'vs/platform/workspace/common/workspace'; import {AIAdapter, IAIAdapter} from 'vs/base/node/aiAdapter'; import winreg = require('winreg'); import os = require('os'); -namespace StorageKeys { +export namespace StorageKeys { export const sqmUserId: string = 'telemetry.sqm.userId'; export const sqmMachineId: string = 'telemetry.sqm.machineId'; export const lastSessionDate: string = 'telemetry.lastSessionDate'; @@ -21,8 +20,7 @@ namespace StorageKeys { export class AppInsightsAppender implements ITelemetryAppender { - public static EVENT_NAME_PREFIX: string = 'monacoworkbench'; - + private static EVENT_NAME_PREFIX: string = 'monacoworkbench'; private static SQM_KEY: string = '\\Software\\Microsoft\\SQMClient'; private storageService: IStorageService; @@ -33,32 +31,27 @@ export class AppInsightsAppender implements ITelemetryAppender { constructor( @IStorageService storageService: IStorageService, - env: IEnvironment, - _testing_client?: any + config: {key: string; asimovKey: string}, + _testing_client?: IAIAdapter ) { this.commonProperties = {}; this.commonMetrics = {}; this.storageService = storageService; - let key = env.aiConfig && env.aiConfig.key; - let asimovKey = env.aiConfig && env.aiConfig.asimovKey; - - // for test + let {key, asimovKey} = config; if (_testing_client) { + // for test this.appInsights = _testing_client; - if (asimovKey) { this.appInsightsVortex = _testing_client; } - return; - } - - if (key) { - this.appInsights = new AIAdapter(AppInsightsAppender.EVENT_NAME_PREFIX, undefined, key); - } - - if (asimovKey) { - this.appInsightsVortex = new AIAdapter(AppInsightsAppender.EVENT_NAME_PREFIX, undefined, asimovKey); + } else { + if (key) { + this.appInsights = new AIAdapter(AppInsightsAppender.EVENT_NAME_PREFIX, undefined, key); + } + if (asimovKey) { + this.appInsightsVortex = new AIAdapter(AppInsightsAppender.EVENT_NAME_PREFIX, undefined, asimovKey); + } } this.loadAddtionaProperties(); diff --git a/src/vs/platform/telemetry/test/node/appInsightsAppender.test.ts b/src/vs/platform/telemetry/test/node/appInsightsAppender.test.ts index 8d47c26610f..c2e3191242f 100644 --- a/src/vs/platform/telemetry/test/node/appInsightsAppender.test.ts +++ b/src/vs/platform/telemetry/test/node/appInsightsAppender.test.ts @@ -6,7 +6,8 @@ import * as assert from 'assert'; import {IAIAdapter} from 'vs/base/node/aiAdapter'; -import {AppInsightsAppender} from 'vs/platform/telemetry/node/appInsightsAppender'; +import {AppInsightsAppender, StorageKeys} from 'vs/platform/telemetry/node/appInsightsAppender'; +import {TestStorageService} from 'vs/workbench/test/browser/servicesTestUtils'; interface IAppInsightsEvent { eventName: string; @@ -19,7 +20,7 @@ class AIAdapterMock implements IAIAdapter { public IsTrackingPageView: boolean = false; public exceptions: any[] =[]; - constructor(private prefix: string, private eventPrefix: string, client?: any) { + constructor(private prefix: string) { } public log(eventName: string, data?: any): void { @@ -37,27 +38,13 @@ class AIAdapterMock implements IAIAdapter { } } -let envKeyNoAsimov: any = { - aiConfig: { - key: '123', - asimovKey: undefined - } -}; - -let envKeyAsimov: any = { - aiConfig: { - key: '123', - asimovKey: 'AIF-123' - } -}; - suite('Telemetry - AppInsightsTelemetryAppender', () => { var appInsightsMock: AIAdapterMock; var appender: AppInsightsAppender; setup(() => { - appInsightsMock = new AIAdapterMock(AppInsightsAppender.EVENT_NAME_PREFIX, AppInsightsAppender.EVENT_NAME_PREFIX); - appender = new AppInsightsAppender(null, envKeyNoAsimov, appInsightsMock); + appInsightsMock = new AIAdapterMock('testPrefix'); + appender = new AppInsightsAppender(new TestStorageService(), { key: '123', asimovKey: undefined }, appInsightsMock); }); teardown(() => { @@ -68,7 +55,35 @@ suite('Telemetry - AppInsightsTelemetryAppender', () => { appender.log('testEvent'); assert.equal(appInsightsMock.events.length, 1); - assert.equal(appInsightsMock.events[0].eventName, AppInsightsAppender.EVENT_NAME_PREFIX+'/testEvent'); + assert.equal(appInsightsMock.events[0].eventName, 'testPrefix/testEvent'); + }); + + test('test additional properties', () => { + appender.log('testEvent'); + assert.equal(appInsightsMock.events.length, 1); + + let [first] = appInsightsMock.events; + assert.equal(first.eventName, 'testPrefix/testEvent'); + assert.ok('common.osVersion' in first.data); + assert.ok('common.isNewSession' in first.data); + assert.ok('common.firstSessionDate' in first.data); + assert.ok(!('common.lastSessionDate' in first.data)); // conditional, see below + // assert.ok('common.version.shell' in first.data); // only when running on electron + // assert.ok('common.version.renderer' in first.data); + if (process.platform === 'win32') { // SQM only on windows + assert.ok('common.sqm.userid' in first.data); + assert.ok('common.sqm.machineid' in first.data); + } + }); + + test('test additional properties with storage data', () => { + const storage = new TestStorageService(); + storage.store(StorageKeys.lastSessionDate, 'somevalue'); + let appender = new AppInsightsAppender(storage, { key: '123', asimovKey: undefined }, appInsightsMock); + appender.log('testEvent'); + let [first] = appInsightsMock.events; + assert.ok('common.lastSessionDate' in first.data); // conditional + appender.dispose(); }); test('Event with data', () => { @@ -79,7 +94,7 @@ suite('Telemetry - AppInsightsTelemetryAppender', () => { }); assert.equal(appInsightsMock.events.length, 1); - assert.equal(appInsightsMock.events[0].eventName, AppInsightsAppender.EVENT_NAME_PREFIX+'/testEvent'); + assert.equal(appInsightsMock.events[0].eventName, 'testPrefix/testEvent'); assert.equal(appInsightsMock.events[0].data['title'], 'some title'); assert.equal(appInsightsMock.events[0].data['width'], 100); @@ -88,14 +103,14 @@ suite('Telemetry - AppInsightsTelemetryAppender', () => { }); test('Test asimov', () => { - appender = new AppInsightsAppender(null, envKeyAsimov, appInsightsMock); + appender = new AppInsightsAppender(new TestStorageService(), { key: '123', asimovKey: 'AIF-123' }, appInsightsMock); appender.log('testEvent'); assert.equal(appInsightsMock.events.length, 2); - assert.equal(appInsightsMock.events[0].eventName, AppInsightsAppender.EVENT_NAME_PREFIX+'/testEvent'); + assert.equal(appInsightsMock.events[0].eventName, 'testPrefix/testEvent'); // test vortex - assert.equal(appInsightsMock.events[1].eventName, AppInsightsAppender.EVENT_NAME_PREFIX+'/testEvent'); + assert.equal(appInsightsMock.events[1].eventName, 'testPrefix/testEvent'); }); }); \ No newline at end of file diff --git a/src/vs/workbench/electron-browser/shell.ts b/src/vs/workbench/electron-browser/shell.ts index 9d2a41e984e..06269ed1488 100644 --- a/src/vs/workbench/electron-browser/shell.ts +++ b/src/vs/workbench/electron-browser/shell.ts @@ -209,7 +209,7 @@ export class WorkbenchShell { extensionsRoot: this.configuration.env.userExtensionsHome, version: this.configuration.env.version, commitHash: this.configuration.env.commitHash, - appender: [new AppInsightsAppender(this.storageService, this.configuration.env)] + appender: [new AppInsightsAppender(this.storageService, this.configuration.env.aiConfig)] }); } else { this.telemetryService = NullTelemetryService; From 248f556e1ab30947ecf164125164bb8d23cf7e70 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 6 May 2016 18:29:41 +0200 Subject: [PATCH 099/297] simplify extra properties logic such that it be moved soon --- src/vs/platform/telemetry/common/telemetry.ts | 2 +- .../telemetry/node/appInsightsAppender.ts | 152 ++++++++---------- .../test/node/appInsightsAppender.test.ts | 75 ++++----- 3 files changed, 107 insertions(+), 122 deletions(-) diff --git a/src/vs/platform/telemetry/common/telemetry.ts b/src/vs/platform/telemetry/common/telemetry.ts index 5c8ea8ef9bf..1da414e865d 100644 --- a/src/vs/platform/telemetry/common/telemetry.ts +++ b/src/vs/platform/telemetry/common/telemetry.ts @@ -51,7 +51,7 @@ export const NullTelemetryService: ITelemetryService = { }; export interface ITelemetryAppender extends IDisposable { - log(eventName: string, data?: any): void; + log(eventName: string, data?: any): any; } // --- util diff --git a/src/vs/platform/telemetry/node/appInsightsAppender.ts b/src/vs/platform/telemetry/node/appInsightsAppender.ts index e31a974857d..18f73cb40e7 100644 --- a/src/vs/platform/telemetry/node/appInsightsAppender.ts +++ b/src/vs/platform/telemetry/node/appInsightsAppender.ts @@ -5,6 +5,8 @@ 'use strict'; import errors = require('vs/base/common/errors'); +import {TPromise} from 'vs/base/common/winjs.base'; +import {mixin} from 'vs/base/common/objects'; import {IStorageService} from 'vs/platform/storage/common/storage'; import {ITelemetryAppender} from 'vs/platform/telemetry/common/telemetry'; import {AIAdapter, IAIAdapter} from 'vs/base/node/aiAdapter'; @@ -23,21 +25,15 @@ export class AppInsightsAppender implements ITelemetryAppender { private static EVENT_NAME_PREFIX: string = 'monacoworkbench'; private static SQM_KEY: string = '\\Software\\Microsoft\\SQMClient'; - private storageService: IStorageService; private appInsights: IAIAdapter; private appInsightsVortex: IAIAdapter; - private commonProperties: { [key: string]: string }; - private commonMetrics: { [key: string]: number }; + private _additionalProperties: TPromise<{ [key: string]: any }>; constructor( @IStorageService storageService: IStorageService, config: {key: string; asimovKey: string}, _testing_client?: IAIAdapter ) { - this.commonProperties = {}; - this.commonMetrics = {}; - this.storageService = storageService; - let {key, asimovKey} = config; if (_testing_client) { // for test @@ -54,130 +50,118 @@ export class AppInsightsAppender implements ITelemetryAppender { } } - this.loadAddtionaProperties(); + this._additionalProperties = AppInsightsAppender._loadAddtionalProperties(storageService); } - private loadAddtionaProperties(): void { + private static _loadAddtionalProperties(storageService: IStorageService): TPromise<{ [key: string]: any }> { + + const result: { [key: string]: any } = Object.create(null); + let promises: TPromise[] = []; + // add shell & render version if (process.versions) { - this.commonProperties['version.shell'] = (process).versions['electron']; - this.commonProperties['version.renderer'] = (process).versions['chrome']; + result['common.version.shell'] = (process).versions['electron']; + result['common.version.renderer'] = (process).versions['chrome']; } // add SQM data for windows machines if (process.platform === 'win32') { - var sqmUserId = this.storageService.get(StorageKeys.sqmUserId); + var sqmUserId = storageService.get(StorageKeys.sqmUserId); if (sqmUserId) { - this.commonProperties['sqm.userid'] = sqmUserId; + result['common.sqm.userid'] = sqmUserId; } else { - AppInsightsAppender._getWinRegKeyData(AppInsightsAppender.SQM_KEY, 'UserId', winreg.HKCU, (error, result: string) => { - if (!error && result) { - this.commonProperties['sqm.userid'] = result; - this.storageService.store(StorageKeys.sqmUserId, result); + promises.push(AppInsightsAppender._getWinRegKeyData(AppInsightsAppender.SQM_KEY, 'UserId', winreg.HKCU).then(result => { + if (result) { + result['common.sqm.userid'] = result; + storageService.store(StorageKeys.sqmUserId, result); } - }); + })); } - var sqmMachineId = this.storageService.get(StorageKeys.sqmMachineId); + var sqmMachineId = storageService.get(StorageKeys.sqmMachineId); if (sqmMachineId) { - this.commonProperties['sqm.machineid'] = sqmMachineId; + result['common.sqm.machineid'] = sqmMachineId; } else { - AppInsightsAppender._getWinRegKeyData(AppInsightsAppender.SQM_KEY, 'MachineId', winreg.HKLM, (error, result) => { - if (!error && result) { - this.commonProperties['sqm.machineid'] = result; - this.storageService.store(StorageKeys.sqmMachineId, result); + promises.push(AppInsightsAppender._getWinRegKeyData(AppInsightsAppender.SQM_KEY, 'MachineId', winreg.HKLM).then(result => { + if (result) { + result['common.sqm.machineid'] = result; + storageService.store(StorageKeys.sqmMachineId, result); } - }); + })); } } - var firstSessionDate = this.storageService.get(StorageKeys.firstSessionDate); + var firstSessionDate = storageService.get(StorageKeys.firstSessionDate); if (!firstSessionDate) { firstSessionDate = (new Date()).toUTCString(); - this.storageService.store(StorageKeys.firstSessionDate, firstSessionDate); + storageService.store(StorageKeys.firstSessionDate, firstSessionDate); } - this.commonProperties['firstSessionDate'] = firstSessionDate; + result['common.firstSessionDate'] = firstSessionDate; //report last session date and isNewSession flag - var lastSessionDate = this.storageService.get(StorageKeys.lastSessionDate); + var lastSessionDate = storageService.get(StorageKeys.lastSessionDate); if (!lastSessionDate) { - this.commonMetrics['isNewSession'] = 1; + result['common.isNewSession'] = 1; } else { - this.commonMetrics['isNewSession'] = 0; - this.commonProperties['lastSessionDate'] = lastSessionDate; + result['common.isNewSession'] = 0; + result['common.lastSessionDate'] = lastSessionDate; } - this.storageService.store(StorageKeys.lastSessionDate, (new Date()).toUTCString()); + storageService.store(StorageKeys.lastSessionDate, (new Date()).toUTCString()); if (os) { - this.commonProperties['osVersion'] = os.release(); + result['common.osVersion'] = os.release(); } + + return TPromise.join(promises).then(() => result, () => result); } - private static _getWinRegKeyData(key: string, name: string, hive: string, callback: (error: Error, userId: string) => void): void { - if (process.platform === 'win32') { - try { - var reg = new winreg({ - hive: hive, - key: key - }); - - reg.get(name, (e, result) => { - if (e || !result) { - callback(e, null); - } else { - callback(null, result.value); - } - }); - } catch (err) { - errors.onUnexpectedError(err); - callback(err, null); + private static _getWinRegKeyData(key: string, name: string, hive: string): TPromise { + return new TPromise((resolve, reject) => { + if (process.platform === 'win32') { + try { + var reg = new winreg({ hive, key }); + reg.get(name, (e, result) => { + if (e || !result) { + reject(null); + } else { + resolve(result.value); + } + }); + } catch (err) { + errors.onUnexpectedError(err); + reject(err); + } + } else { + resolve(null); } - } else { - callback(null, null); - } + }).then(undefined, err => { + // we only want success + return undefined; + }); } - public log(eventName: string, data?: any): void { - - data = data || Object.create(null); - data = this.addCommonMetrics(data); - data = this.addCommonProperties(data); - - if (this.appInsights) { - this.appInsights.log(eventName, data); - } - - if (this.appInsightsVortex) { - this.appInsightsVortex.log(eventName, data); - } + public log(eventName: string, data?: any): TPromise { + return this._additionalProperties.then(additionalProperties => { + data = mixin(data, additionalProperties); + if (this.appInsights) { + this.appInsights.log(eventName, data); + } + if (this.appInsightsVortex) { + this.appInsightsVortex.log(eventName, data); + } + }); } public dispose(): void { if (this.appInsights) { this.appInsights.dispose(); } - if (this.appInsightsVortex) { this.appInsightsVortex.dispose(); } - this.appInsights = null; this.appInsightsVortex = null; } - - protected addCommonProperties(properties: any): any { - for (var prop in this.commonProperties) { - properties['common.' + prop] = this.commonProperties[prop]; - } - return properties; - } - - protected addCommonMetrics(metrics: any): any { - for (var prop in this.commonMetrics) { - metrics['common.' + prop] = this.commonMetrics[prop]; - } - return metrics; - } } \ No newline at end of file diff --git a/src/vs/platform/telemetry/test/node/appInsightsAppender.test.ts b/src/vs/platform/telemetry/test/node/appInsightsAppender.test.ts index c2e3191242f..51e19ad5f0a 100644 --- a/src/vs/platform/telemetry/test/node/appInsightsAppender.test.ts +++ b/src/vs/platform/telemetry/test/node/appInsightsAppender.test.ts @@ -52,65 +52,66 @@ suite('Telemetry - AppInsightsTelemetryAppender', () => { }); test('Simple event', () => { - appender.log('testEvent'); - - assert.equal(appInsightsMock.events.length, 1); - assert.equal(appInsightsMock.events[0].eventName, 'testPrefix/testEvent'); + return appender.log('testEvent').then(_ => { + assert.equal(appInsightsMock.events.length, 1); + assert.equal(appInsightsMock.events[0].eventName, 'testPrefix/testEvent'); + }); }); test('test additional properties', () => { - appender.log('testEvent'); - assert.equal(appInsightsMock.events.length, 1); + return appender.log('testEvent').then(_ => { + assert.equal(appInsightsMock.events.length, 1); - let [first] = appInsightsMock.events; - assert.equal(first.eventName, 'testPrefix/testEvent'); - assert.ok('common.osVersion' in first.data); - assert.ok('common.isNewSession' in first.data); - assert.ok('common.firstSessionDate' in first.data); - assert.ok(!('common.lastSessionDate' in first.data)); // conditional, see below - // assert.ok('common.version.shell' in first.data); // only when running on electron - // assert.ok('common.version.renderer' in first.data); - if (process.platform === 'win32') { // SQM only on windows - assert.ok('common.sqm.userid' in first.data); - assert.ok('common.sqm.machineid' in first.data); - } + let [first] = appInsightsMock.events; + assert.equal(first.eventName, 'testPrefix/testEvent'); + assert.ok('common.osVersion' in first.data); + assert.ok('common.isNewSession' in first.data); + assert.ok('common.firstSessionDate' in first.data); + assert.ok(!('common.lastSessionDate' in first.data)); // conditional, see below + // assert.ok('common.version.shell' in first.data); // only when running on electron + // assert.ok('common.version.renderer' in first.data); + if (process.platform === 'win32') { // SQM only on windows + assert.ok('common.sqm.userid' in first.data); + assert.ok('common.sqm.machineid' in first.data); + } + }); }); test('test additional properties with storage data', () => { const storage = new TestStorageService(); storage.store(StorageKeys.lastSessionDate, 'somevalue'); let appender = new AppInsightsAppender(storage, { key: '123', asimovKey: undefined }, appInsightsMock); - appender.log('testEvent'); - let [first] = appInsightsMock.events; - assert.ok('common.lastSessionDate' in first.data); // conditional - appender.dispose(); + return appender.log('testEvent').then(_ => { + let [first] = appInsightsMock.events; + assert.ok('common.lastSessionDate' in first.data); // conditional + appender.dispose(); + }); }); test('Event with data', () => { - appender.log('testEvent', { + return appender.log('testEvent', { title: 'some title', width: 100, height: 200 + }).then(_ => { + assert.equal(appInsightsMock.events.length, 1); + assert.equal(appInsightsMock.events[0].eventName, 'testPrefix/testEvent'); + + assert.equal(appInsightsMock.events[0].data['title'], 'some title'); + assert.equal(appInsightsMock.events[0].data['width'], 100); + assert.equal(appInsightsMock.events[0].data['height'], 200); }); - - assert.equal(appInsightsMock.events.length, 1); - assert.equal(appInsightsMock.events[0].eventName, 'testPrefix/testEvent'); - - assert.equal(appInsightsMock.events[0].data['title'], 'some title'); - assert.equal(appInsightsMock.events[0].data['width'], 100); - assert.equal(appInsightsMock.events[0].data['height'], 200); - }); test('Test asimov', () => { appender = new AppInsightsAppender(new TestStorageService(), { key: '123', asimovKey: 'AIF-123' }, appInsightsMock); - appender.log('testEvent'); + return appender.log('testEvent').then(_ => { + assert.equal(appInsightsMock.events.length, 2); + assert.equal(appInsightsMock.events[0].eventName, 'testPrefix/testEvent'); - assert.equal(appInsightsMock.events.length, 2); - assert.equal(appInsightsMock.events[0].eventName, 'testPrefix/testEvent'); - - // test vortex - assert.equal(appInsightsMock.events[1].eventName, 'testPrefix/testEvent'); + // test vortex + assert.equal(appInsightsMock.events[1].eventName, 'testPrefix/testEvent'); + }); }); }); \ No newline at end of file From 58f560d120c1bfad5264efd11f14e48a49bc6bee Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 6 May 2016 18:50:30 +0200 Subject: [PATCH 100/297] add test for default properties telemetry service adds --- .../test/node/telemetryService.test.ts | 29 ++++++++++++++++--- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/src/vs/platform/telemetry/test/node/telemetryService.test.ts b/src/vs/platform/telemetry/test/node/telemetryService.test.ts index 75401ac7183..a60202c167f 100644 --- a/src/vs/platform/telemetry/test/node/telemetryService.test.ts +++ b/src/vs/platform/telemetry/test/node/telemetryService.test.ts @@ -25,10 +25,7 @@ class TestTelemetryAppender implements Telemetry.ITelemetryAppender { } public log(eventName: string, data?: any): void { - this.events.push({ - eventName: eventName, - data: data - }); + this.events.push({ eventName, data }); } public getEventsCount() { @@ -134,6 +131,30 @@ suite('TelemetryService', () => { }); })); + test('default properties', function () { + let testAppender = new TestTelemetryAppender(); + let service = new TelemetryService({ appender: [testAppender] }); + + return service.getTelemetryInfo().then(info => { + + service.publicLog('testEvent'); + let [first] = testAppender.events; + + assert.equal(Object.keys(first.data).length, 9); + assert.ok('sessionID' in first.data); + assert.ok('timestamp' in first.data); + assert.ok('version' in first.data); + assert.ok('commitHash' in first.data); + assert.ok('common.platform' in first.data); + assert.ok('common.timesincesessionstart' in first.data); + assert.ok('common.sequence' in first.data); + assert.ok('common.instanceId' in first.data); + assert.ok('common.machineId' in first.data); + + service.dispose(); + }); + }); + test('Event with data', sinon.test(function() { let testAppender = new TestTelemetryAppender(); let service = new TelemetryService({ appender: [testAppender] }); From 7ace9f8c48e3ce66de9617b30b56648e627134a7 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 6 May 2016 18:52:09 +0200 Subject: [PATCH 101/297] sessionId is always uuid + date --- src/vs/platform/telemetry/browser/telemetryService.ts | 5 +---- .../telemetry/test/node/telemetryService.test.ts | 11 ----------- 2 files changed, 1 insertion(+), 15 deletions(-) diff --git a/src/vs/platform/telemetry/browser/telemetryService.ts b/src/vs/platform/telemetry/browser/telemetryService.ts index 4fe3b6ec036..f3a35929e09 100644 --- a/src/vs/platform/telemetry/browser/telemetryService.ts +++ b/src/vs/platform/telemetry/browser/telemetryService.ts @@ -21,7 +21,6 @@ export interface ITelemetryServiceConfig { userOptIn?: boolean; enableHardIdle?: boolean; enableSoftIdle?: boolean; - sessionID?: string; commitHash?: string; version?: string; appRoot?: string; @@ -54,8 +53,6 @@ export class TelemetryService implements ITelemetryService { constructor(config?: ITelemetryServiceConfig) { this._configuration = withDefaults(config, { appender: [], - cleanupPatterns: [], - sessionID: uuid.generateUuid() + Date.now(), enableHardIdle: true, enableSoftIdle: true, userOptIn: true @@ -78,7 +75,7 @@ export class TelemetryService implements ITelemetryService { ); this._telemetryInfo = { - sessionId: this._configuration.sessionID, + sessionId: uuid.generateUuid() + Date.now(), instanceId: undefined, machineId: undefined }; diff --git a/src/vs/platform/telemetry/test/node/telemetryService.test.ts b/src/vs/platform/telemetry/test/node/telemetryService.test.ts index a60202c167f..5830589a817 100644 --- a/src/vs/platform/telemetry/test/node/telemetryService.test.ts +++ b/src/vs/platform/telemetry/test/node/telemetryService.test.ts @@ -650,17 +650,6 @@ suite('TelemetryService', () => { service.dispose(); })); - test('Telemetry Service uses provided session ID', sinon.test(function() { - - let testSessionId = 'test session id'; - let service = new TelemetryService({ sessionID: testSessionId, appender: [] }); - - return service.getTelemetryInfo().then(info => { - assert.equal(info.sessionId, testSessionId); - service.dispose(); - }); - })); - test('Telemetry Service respects user opt-in settings', sinon.test(function() { let testAppender = new TestTelemetryAppender(); let service = new TelemetryService({userOptIn: false, appender: [testAppender] }); From 65966e3096bb2a3a8b316927875c7a914dc68e19 Mon Sep 17 00:00:00 2001 From: Erich Gamma Date: Sun, 8 May 2016 10:06:29 +0200 Subject: [PATCH 102/297] Map 'stylus' language to 'css' to fix #6062 --- src/vs/workbench/parts/emmet/node/editorAccessor.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/vs/workbench/parts/emmet/node/editorAccessor.ts b/src/vs/workbench/parts/emmet/node/editorAccessor.ts index 9498d7328ea..b392b347746 100644 --- a/src/vs/workbench/parts/emmet/node/editorAccessor.ts +++ b/src/vs/workbench/parts/emmet/node/editorAccessor.ts @@ -124,6 +124,9 @@ export class EditorAccessor implements emmet.Editor { if (syntax === 'sass') { // sass is really sccs... map it to scss return'scss'; } + if (syntax === 'stylus') { // map stylus to css + return'css'; + } return syntax; } From 9430393ba97ba3529881bd53994f0814285d5b07 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Mon, 9 May 2016 11:10:28 +0200 Subject: [PATCH 103/297] Remove win32 assertion in appInsightsAppender test --- .../telemetry/test/node/appInsightsAppender.test.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/vs/platform/telemetry/test/node/appInsightsAppender.test.ts b/src/vs/platform/telemetry/test/node/appInsightsAppender.test.ts index 51e19ad5f0a..efbb6b52081 100644 --- a/src/vs/platform/telemetry/test/node/appInsightsAppender.test.ts +++ b/src/vs/platform/telemetry/test/node/appInsightsAppender.test.ts @@ -70,10 +70,11 @@ suite('Telemetry - AppInsightsTelemetryAppender', () => { assert.ok(!('common.lastSessionDate' in first.data)); // conditional, see below // assert.ok('common.version.shell' in first.data); // only when running on electron // assert.ok('common.version.renderer' in first.data); - if (process.platform === 'win32') { // SQM only on windows - assert.ok('common.sqm.userid' in first.data); - assert.ok('common.sqm.machineid' in first.data); - } + // TODO@Joh: This is not always there... + // if (process.platform === 'win32') { // SQM only on windows + // assert.ok('common.sqm.userid' in first.data); + // assert.ok('common.sqm.machineid' in first.data); + // } }); }); From 7d1251f171e8b9e4f68a712c9a94b5b45e94aaa7 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Mon, 9 May 2016 12:24:38 +0200 Subject: [PATCH 104/297] fixes #6176: Go to/Peek Definition and Find all References in CSS --- src/vs/languages/css/common/css.ts | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/vs/languages/css/common/css.ts b/src/vs/languages/css/common/css.ts index 62d55d79017..203566d1013 100644 --- a/src/vs/languages/css/common/css.ts +++ b/src/vs/languages/css/common/css.ts @@ -19,8 +19,6 @@ import {IInstantiationService} from 'vs/platform/instantiation/common/instantiat import {IThreadService, ThreadAffinity} from 'vs/platform/thread/common/thread'; import {RichEditSupport} from 'vs/editor/common/modes/supports/richEditSupport'; import {TokenizationSupport} from 'vs/editor/common/modes/supports/tokenizationSupport'; -import {DeclarationSupport} from 'vs/editor/common/modes/supports/declarationSupport'; -import {ReferenceSupport} from 'vs/editor/common/modes/supports/referenceSupport'; import {SuggestSupport} from 'vs/editor/common/modes/supports/suggestSupport'; export enum States { @@ -336,16 +334,16 @@ export class CSSMode extends AbstractMode { this.inplaceReplaceSupport = this; this.configSupport = this; - this.occurrencesSupport = this; + //this.occurrencesSupport = this; this.extraInfoSupport = this; - this.referenceSupport = new ReferenceSupport(this.getId(), { - tokens: [cssTokenTypes.TOKEN_PROPERTY + '.css', cssTokenTypes.TOKEN_VALUE + '.css', cssTokenTypes.TOKEN_SELECTOR_TAG + '.css'], - findReferences: (resource, position, /*unused*/includeDeclaration) => this.findReferences(resource, position)}); + // this.referenceSupport = new ReferenceSupport(this.getId(), { + // tokens: [cssTokenTypes.TOKEN_PROPERTY + '.css', cssTokenTypes.TOKEN_VALUE + '.css', cssTokenTypes.TOKEN_SELECTOR_TAG + '.css'], + // findReferences: (resource, position, /*unused*/includeDeclaration) => this.findReferences(resource, position)}); this.logicalSelectionSupport = this; this.outlineSupport = this; - this.declarationSupport = new DeclarationSupport(this.getId(), { - tokens: [cssTokenTypes.TOKEN_VALUE + '.css'], - findDeclaration: (resource, position) => this.findDeclaration(resource, position)}); + // this.declarationSupport = new DeclarationSupport(this.getId(), { + // tokens: [cssTokenTypes.TOKEN_VALUE + '.css'], + // findDeclaration: (resource, position) => this.findDeclaration(resource, position)}); this.suggestSupport = new SuggestSupport(this.getId(), { triggerCharacters: [' ', ':'], From 9143a5b455b5eb2db2d94c9156a870050f00df1a Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Mon, 9 May 2016 12:56:46 +0200 Subject: [PATCH 105/297] Fixes #5649: Allow extension activation only after the main process acknowledges its receival of the ext descriptions --- .../extensions/common/nativeExtensionService.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/vs/platform/extensions/common/nativeExtensionService.ts b/src/vs/platform/extensions/common/nativeExtensionService.ts index 1ec4c63944a..f3af4b51d9d 100644 --- a/src/vs/platform/extensions/common/nativeExtensionService.ts +++ b/src/vs/platform/extensions/common/nativeExtensionService.ts @@ -133,10 +133,11 @@ export class MainProcessExtensionService extends AbstractExtensionService { ExtensionsRegistry.registerExtensions(extensionDescriptions); messages.forEach((entry) => this._handleMessage(entry)); this._triggerOnReady(); + return; } public $onExtensionActivated(extensionId: string): void { @@ -248,7 +249,7 @@ export class ExtHostExtensionService extends AbstractExtensionService { + // Wait for the main process to acknowledge its receival of the extensions descriptions + // before allowing extensions to be activated + this._triggerOnReady(); + }); } // -- overwriting AbstractExtensionService From 1759568b8b6df4fbb53400f75801607fd43334f4 Mon Sep 17 00:00:00 2001 From: isidor Date: Mon, 9 May 2016 13:02:50 +0200 Subject: [PATCH 106/297] debug: if exitCode for preLaunchTask is present and success just start debug session #5962 --- src/vs/workbench/parts/debug/electron-browser/debugService.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/parts/debug/electron-browser/debugService.ts b/src/vs/workbench/parts/debug/electron-browser/debugService.ts index f71929dce75..45eadde5995 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugService.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugService.ts @@ -512,8 +512,9 @@ export class DebugService implements debug.IDebugService { return this.runPreLaunchTask(configuration.preLaunchTask).then((taskSummary: ITaskSummary) => { const errorCount = configuration.preLaunchTask ? this.markerService.getStatistics().errors : 0; + const successExitCode = taskSummary && taskSummary.exitCode === 0; const failureExitCode = taskSummary && taskSummary.exitCode !== undefined && taskSummary.exitCode !== 0; - if (errorCount === 0 && !failureExitCode) { + if (successExitCode || (errorCount === 0 && !failureExitCode)) { return this.doCreateSession(configuration, changeViewState); } From 85cf68c4f7cbdc310f050b2eac72e781a7a7bf17 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Mon, 9 May 2016 14:30:22 +0200 Subject: [PATCH 107/297] fixes #6169; Quick fix: inherit font from workbench and do not set it --- src/vs/editor/contrib/quickFix/browser/quickFix.css | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/vs/editor/contrib/quickFix/browser/quickFix.css b/src/vs/editor/contrib/quickFix/browser/quickFix.css index 4073ecef51a..e2138d99a9c 100644 --- a/src/vs/editor/contrib/quickFix/browser/quickFix.css +++ b/src/vs/editor/contrib/quickFix/browser/quickFix.css @@ -92,12 +92,6 @@ color: #A21B1B; } -.monaco-editor .quickfix-widget .monaco-tree .monaco-tree-row > .content .docs { font-family: "Segoe UI", "SFUIText-Regular", "HelveticaNeue", sans-serif, "Droid Sans Fallback"; } -.monaco-editor:lang(zh-Hans) .quickfix-widget .monaco-tree .monaco-tree-row > .content .docs { font-family: "Segoe UI", "SFUIText-Regular", "HelveticaNeue", "Noto Sans", "Microsoft YaHei", "PingFang SC", "Hiragino Sans GB", "Source Han Sans SC", "Source Han Sans CN", "Source Han Sans", sans-serif; } -.monaco-editor:lang(zh-Hant) .quickfix-widget .monaco-tree .monaco-tree-row > .content .docs { font-family: "Segoe UI", "SFUIText-Regular", "HelveticaNeue", "Noto Sans", "Microsoft Jhenghei", "PingFang TC", "Source Han Sans TC", "Source Han Sans", "Source Han Sans TW", sans-serif; } -.monaco-editor:lang(ja) .quickfix-widget .monaco-tree .monaco-tree-row > .content .docs { font-family: "Segoe UI", "SFUIText-Regular", "HelveticaNeue", "Noto Sans", "Meiryo", "Hiragino Kaku Gothic Pro", "Source Han Sans J", "Source Han Sans JP", "Source Han Sans", "Sazanami Gothic", "IPA Gothic", sans-serif; } -.monaco-editor:lang(ko) .quickfix-widget .monaco-tree .monaco-tree-row > .content .docs { font-family: "Segoe UI", "SFUIText-Regular", "HelveticaNeue", "Noto Sans", "Malgun Gothic", "Nanum Gothic", "Dotom", "Apple SD Gothic Neo", "AppleGothic", "Source Han Sans K", "Source Han Sans JR", "Source Han Sans", "UnDotum", "FBaekmuk Gulim", sans-serif; } - .monaco-editor .quickfix-widget .monaco-tree .monaco-tree-row.fake > .content .docs, .monaco-editor .quickfix-widget .monaco-tree .monaco-tree-row.focused > .content .docs { display: block; From 12ac396c6168f49b220911057ce6b7601e36ec19 Mon Sep 17 00:00:00 2001 From: Andre Weinand Date: Mon, 9 May 2016 14:42:00 +0200 Subject: [PATCH 108/297] update node-debug --- extensions/node-debug/node-debug.azure.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/node-debug/node-debug.azure.json b/extensions/node-debug/node-debug.azure.json index 82b4ca4fa36..f9b9a03d58c 100644 --- a/extensions/node-debug/node-debug.azure.json +++ b/extensions/node-debug/node-debug.azure.json @@ -1,6 +1,6 @@ { "account": "monacobuild", "container": "debuggers", - "zip": "4effb16/node-debug.zip", + "zip": "944c79e/node-debug.zip", "output": "" } From f793a7c5fc667b8a97870e5fca1b903dc5e373a0 Mon Sep 17 00:00:00 2001 From: isidor Date: Mon, 9 May 2016 15:23:16 +0200 Subject: [PATCH 109/297] debug: display call stack error from adapter fixes #6100 --- .../parts/debug/browser/debugViewer.ts | 27 +++++++++++++++++++ .../debug/browser/media/debugViewlet.css | 6 +++++ src/vs/workbench/parts/debug/common/debug.ts | 1 + .../parts/debug/common/debugModel.ts | 3 +++ 4 files changed, 37 insertions(+) diff --git a/src/vs/workbench/parts/debug/browser/debugViewer.ts b/src/vs/workbench/parts/debug/browser/debugViewer.ts index ac626c494ee..087e70fcbbc 100644 --- a/src/vs/workbench/parts/debug/browser/debugViewer.ts +++ b/src/vs/workbench/parts/debug/browser/debugViewer.ts @@ -241,6 +241,9 @@ export class CallStackDataSource implements tree.IDataSource { if (typeof element === 'number') { return element.toString(); } + if (typeof element === 'string') { + return element; + } return element.getId(); } @@ -260,6 +263,9 @@ export class CallStackDataSource implements tree.IDataSource { private getThreadChildren(thread: debug.IThread): TPromise { return thread.getCallStack(this.debugService).then((callStack: any[]) => { + if (thread.stoppedDetails.framesErrorMessage) { + return callStack.concat([thread.stoppedDetails.framesErrorMessage]); + } if (thread.stoppedDetails && thread.stoppedDetails.totalFrames > callStack.length) { return callStack.concat([thread.threadId]); } @@ -280,6 +286,10 @@ interface IThreadTemplateData { stateLabel: HTMLSpanElement; } +interface IErrorTemplateData { + label: HTMLElement; +} + interface ILoadMoreTemplateData { label: HTMLElement; } @@ -296,6 +306,7 @@ export class CallStackRenderer implements tree.IRenderer { private static THREAD_TEMPLATE_ID = 'thread'; private static STACK_FRAME_TEMPLATE_ID = 'stackFrame'; + private static ERROR_TEMPLATE_ID = 'error'; private static LOAD_MORE_TEMPLATE_ID = 'loadMore'; constructor( @IWorkspaceContextService private contextService: IWorkspaceContextService) { @@ -313,6 +324,9 @@ export class CallStackRenderer implements tree.IRenderer { if (element instanceof model.StackFrame) { return CallStackRenderer.STACK_FRAME_TEMPLATE_ID; } + if (typeof element === 'string') { + return CallStackRenderer.ERROR_TEMPLATE_ID; + } return CallStackRenderer.LOAD_MORE_TEMPLATE_ID; } @@ -324,6 +338,12 @@ export class CallStackRenderer implements tree.IRenderer { return data; } + if (templateId === CallStackRenderer.ERROR_TEMPLATE_ID) { + let data: ILoadMoreTemplateData = Object.create(null); + data.label = dom.append(container, $('.error')); + + return data; + } if (templateId === CallStackRenderer.THREAD_TEMPLATE_ID) { let data: IThreadTemplateData = Object.create(null); data.thread = dom.append(container, $('.thread')); @@ -349,6 +369,8 @@ export class CallStackRenderer implements tree.IRenderer { this.renderThread(element, templateData); } else if (templateId === CallStackRenderer.STACK_FRAME_TEMPLATE_ID) { this.renderStackFrame(element, templateData); + } else if (templateId === CallStackRenderer.ERROR_TEMPLATE_ID) { + this.renderError(element, templateData); } else { this.renderLoadMore(element, templateData); } @@ -360,6 +382,11 @@ export class CallStackRenderer implements tree.IRenderer { data.stateLabel.textContent = thread.stopped ? nls.localize('paused', "paused") : nls.localize('running', "running"); } + private renderError(element: string, data: IErrorTemplateData) { + data.label.textContent = element; + data.label.title = nls.localize('stackFrameError', "An error occurred while requesting the stack trace"); + } + private renderLoadMore(element: any, data: ILoadMoreTemplateData): void { data.label.textContent = nls.localize('loadMoreStackFrames', "Load More Stack Frames"); } diff --git a/src/vs/workbench/parts/debug/browser/media/debugViewlet.css b/src/vs/workbench/parts/debug/browser/media/debugViewlet.css index 07bfec9ba4c..ce7e59d2a64 100644 --- a/src/vs/workbench/parts/debug/browser/media/debugViewlet.css +++ b/src/vs/workbench/parts/debug/browser/media/debugViewlet.css @@ -187,6 +187,12 @@ text-align: center; } +.debug-viewlet .debug-call-stack .error { + font-style: italic; + text-overflow: ellipsis; + overflow: hidden; +} + /* Variables & Expression view */ .debug-viewlet .scope { diff --git a/src/vs/workbench/parts/debug/common/debug.ts b/src/vs/workbench/parts/debug/common/debug.ts index aba1e3081bf..77597af6779 100644 --- a/src/vs/workbench/parts/debug/common/debug.ts +++ b/src/vs/workbench/parts/debug/common/debug.ts @@ -34,6 +34,7 @@ export interface IRawStoppedDetails { threadId?: number; text?: string; totalFrames?: number; + framesErrorMessage?: string; } // model diff --git a/src/vs/workbench/parts/debug/common/debugModel.ts b/src/vs/workbench/parts/debug/common/debugModel.ts index 138c1f53f42..ae8095d401b 100644 --- a/src/vs/workbench/parts/debug/common/debugModel.ts +++ b/src/vs/workbench/parts/debug/common/debugModel.ts @@ -150,6 +150,9 @@ export class Thread implements debug.IThread { return new StackFrame(this.threadId, rsf.id, rsf.source ? new Source(rsf.source) : new Source({ name: UNKNOWN_SOURCE_LABEL }, false), rsf.name, rsf.line, rsf.column); }); + }, (err: Error) => { + this.stoppedDetails.framesErrorMessage = err.message; + return []; }); } } From 169ecd607149a104d6082e61e2dee14ec633d8fd Mon Sep 17 00:00:00 2001 From: Andre Weinand Date: Mon, 9 May 2016 16:54:37 +0200 Subject: [PATCH 110/297] update node-debug --- extensions/node-debug/node-debug.azure.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/node-debug/node-debug.azure.json b/extensions/node-debug/node-debug.azure.json index f9b9a03d58c..3f6d65e46de 100644 --- a/extensions/node-debug/node-debug.azure.json +++ b/extensions/node-debug/node-debug.azure.json @@ -1,6 +1,6 @@ { "account": "monacobuild", "container": "debuggers", - "zip": "944c79e/node-debug.zip", + "zip": "ae27377/node-debug.zip", "output": "" } From 4ccc89a14a0b3eb397c53e96416196db2b44d964 Mon Sep 17 00:00:00 2001 From: Andre Weinand Date: Mon, 9 May 2016 18:31:45 +0200 Subject: [PATCH 111/297] update node-debug --- extensions/node-debug/node-debug.azure.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/node-debug/node-debug.azure.json b/extensions/node-debug/node-debug.azure.json index 3f6d65e46de..ce55ece0d56 100644 --- a/extensions/node-debug/node-debug.azure.json +++ b/extensions/node-debug/node-debug.azure.json @@ -1,6 +1,6 @@ { "account": "monacobuild", "container": "debuggers", - "zip": "ae27377/node-debug.zip", + "zip": "39a8b11/node-debug.zip", "output": "" } From 7ec3165d504916d695f9d948b88aa36dfc560840 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Mon, 9 May 2016 22:41:38 +0200 Subject: [PATCH 112/297] fixes #5996 [snippets] prefix not matching forward slashes & fixes #4485 [snippets] Allow snippets where the prefix ends with = --- src/vs/editor/common/modes/supports.ts | 54 ++++++++++++++++---------- 1 file changed, 33 insertions(+), 21 deletions(-) diff --git a/src/vs/editor/common/modes/supports.ts b/src/vs/editor/common/modes/supports.ts index 0f57f49baa3..73aa11209e7 100644 --- a/src/vs/editor/common/modes/supports.ts +++ b/src/vs/editor/common/modes/supports.ts @@ -5,6 +5,7 @@ 'use strict'; import * as strings from 'vs/base/common/strings'; +import * as objects from 'vs/base/common/objects'; import {TPromise} from 'vs/base/common/winjs.base'; import {IModel, IPosition} from 'vs/editor/common/editorCommon'; import * as modes from 'vs/editor/common/modes'; @@ -183,32 +184,25 @@ export class SnippetsRegistry { snippetsByMode[path] = snippets; } + // the previous + private static getNonWhitespacePrefix(model: IModel, position: IPosition) { + let line = model.getLineContent(position.lineNumber); + let match = line.match(/[^\s]+$/); + if (match) { + return match[0]; + } + return ''; + } + public static getSnippets(model: IModel, position: IPosition): modes.ISuggestResult { let word = model.getWordAtPosition(position); - let currentPrefix = word ? word.word.substring(0, position.column - word.startColumn) : ''; + let currentWord = word ? word.word.substring(0, position.column - word.startColumn).toLowerCase() : ''; + let currentFullWord = SnippetsRegistry.getNonWhitespacePrefix(model, position).toLowerCase(); let result : modes.ISuggestResult = { - currentWord: currentPrefix, + currentWord: currentWord, suggestions: [] }; - // to avoid that snippets are too prominent in the intellisense proposals: - // - force that the current prefix matches with the snippet prefix - // if there's no prfix, only show snippets at the beginning of the line, or after a whitespace - let filter = null; - if (currentPrefix.length === 0) { - if (position.column > 1) { - let previousCharacter = model.getValueInRange({ startLineNumber: position.lineNumber, startColumn: position.column - 1, endLineNumber: position.lineNumber, endColumn: position.column }); - if (previousCharacter.trim().length !== 0) { - return result; - } - } - } else { - let lowerCasePrefix = currentPrefix.toLowerCase(); - filter = (p: modes.ISuggestion) => { - return strings.startsWith(p.label.toLowerCase(), lowerCasePrefix); - }; - } - let modeId = model.getMode().getId(); let snippets : modes.ISuggestion[]= []; let snipppetsByMode = this._snippets[modeId]; @@ -221,7 +215,25 @@ export class SnippetsRegistry { if (defaultSnippets) { snippets = snippets.concat(defaultSnippets); } - result.suggestions = filter ? snippets.filter(filter) : snippets; + // to avoid that snippets are too prominent in the intellisense proposals: + // enforce that current word is matched or the position is after a whitespace + snippets.forEach(p => { + if (currentWord.length === 0 && currentFullWord.length === 0) { + // if there's no prefix, only show snippets at the beginning of the line, or after a whitespace + } else { + let label = p.label.toLowerCase(); + // force that the current word or full word matches with the snippet prefix + if (currentWord.length > 0 && strings.startsWith(label, currentWord)) { + // ok + } else if (currentFullWord.length > currentWord.length && strings.startsWith(label, currentFullWord)) { + p = objects.clone(p); + p.overwriteBefore = currentFullWord.length; + } else { + return; + } + } + result.suggestions.push(p); + }); // if (result.suggestions.length > 0) { // if (word) { From be9d75f42477f4280b06de844d1024fe96470dac Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 10 May 2016 09:31:13 +0200 Subject: [PATCH 113/297] do not restrict zooming --- src/vs/workbench/electron-browser/actions.ts | 90 +++++++------------ .../workbench/electron-browser/integration.ts | 3 +- 2 files changed, 33 insertions(+), 60 deletions(-) diff --git a/src/vs/workbench/electron-browser/actions.ts b/src/vs/workbench/electron-browser/actions.ts index b6618f88933..217820b5640 100644 --- a/src/vs/workbench/electron-browser/actions.ts +++ b/src/vs/workbench/electron-browser/actions.ts @@ -172,14 +172,36 @@ export class ZoomInAction extends Action { public run(): TPromise { webFrame.setZoomLevel(webFrame.getZoomLevel() + 1); - // Ensure others can listen to zoom level changes - browser.setZoomLevel(webFrame.getZoomLevel()); + browser.setZoomLevel(webFrame.getZoomLevel()); // Ensure others can listen to zoom level changes return TPromise.as(true); } } -export abstract class BaseZoomAction extends Action { +export class ZoomOutAction extends Action { + + public static ID = 'workbench.action.zoomOut'; + public static LABEL = nls.localize('zoomOut', "Zoom out"); + + constructor( + id: string, + label: string + ) { + super(id, label); + } + + public run(): TPromise { + webFrame.setZoomLevel(webFrame.getZoomLevel() - 1); + browser.setZoomLevel(webFrame.getZoomLevel()); // Ensure others can listen to zoom level changes + + return TPromise.as(true); + } +} + +export class ZoomResetAction extends Action { + + public static ID = 'workbench.action.zoomReset'; + public static LABEL = nls.localize('zoomReset', "Reset Zoom"); constructor( id: string, @@ -190,10 +212,14 @@ export abstract class BaseZoomAction extends Action { } public run(): TPromise { - return TPromise.as(false); // Subclass to implement + const level = this.getConfiguredZoomLevel(); + webFrame.setZoomLevel(level); + browser.setZoomLevel(webFrame.getZoomLevel()); // Ensure others can listen to zoom level changes + + return TPromise.as(true); } - protected getConfiguredZoomLevel(): number { + private getConfiguredZoomLevel(): number { const windowConfig = this.configurationService.getConfiguration(); if (windowConfig.window && typeof windowConfig.window.zoomLevel === 'number') { return windowConfig.window.zoomLevel; @@ -203,58 +229,6 @@ export abstract class BaseZoomAction extends Action { } } -export class ZoomOutAction extends BaseZoomAction { - - public static ID = 'workbench.action.zoomOut'; - public static LABEL = nls.localize('zoomOut', "Zoom out"); - - constructor( - id: string, - label: string, - @IConfigurationService configurationService: IConfigurationService - ) { - super(id, label, configurationService); - } - - public run(): TPromise { - const level = this.getConfiguredZoomLevel(); - - let newZoomLevelCandiate = webFrame.getZoomLevel() - 1; - if (newZoomLevelCandiate < 0 && newZoomLevelCandiate < level) { - newZoomLevelCandiate = Math.min(level, 0); // do not zoom below configured level or below 0 - } - - webFrame.setZoomLevel(newZoomLevelCandiate); - // Ensure others can listen to zoom level changes - browser.setZoomLevel(webFrame.getZoomLevel()); - - return TPromise.as(true); - } -} - -export class ZoomResetAction extends BaseZoomAction { - - public static ID = 'workbench.action.zoomReset'; - public static LABEL = nls.localize('zoomReset', "Reset Zoom"); - - constructor( - id: string, - label: string, - @IConfigurationService configurationService: IConfigurationService - ) { - super(id, label, configurationService); - } - - public run(): TPromise { - const level = this.getConfiguredZoomLevel(); - webFrame.setZoomLevel(level); - // Ensure others can listen to zoom level changes - browser.setZoomLevel(webFrame.getZoomLevel()); - - return TPromise.as(true); - } -} - /* Copied from loader.ts */ enum LoaderEventType { LoaderAvailable = 1, @@ -476,7 +450,7 @@ export class CloseMessagesAction extends Action { KeybindingsRegistry.registerCommandDesc({ id: '_workbench.ipc', weight: KeybindingsRegistry.WEIGHT.workbenchContrib(0), - handler(accessor: ServicesAccessor, ipcMessage: string, ipcArgs:any[]) { + handler(accessor: ServicesAccessor, ipcMessage: string, ipcArgs: any[]) { if (ipcMessage && Array.isArray(ipcArgs)) { ipc.send(ipcMessage, ...ipcArgs); } else { diff --git a/src/vs/workbench/electron-browser/integration.ts b/src/vs/workbench/electron-browser/integration.ts index 73816d82363..559367357e9 100644 --- a/src/vs/workbench/electron-browser/integration.ts +++ b/src/vs/workbench/electron-browser/integration.ts @@ -139,8 +139,7 @@ export class ElectronIntegration { if (webFrame.getZoomLevel() !== newZoomLevel) { webFrame.setZoomLevel(newZoomLevel); - // Ensure others can listen to zoom level changes - browser.setZoomLevel(webFrame.getZoomLevel()); + browser.setZoomLevel(webFrame.getZoomLevel()); // Ensure others can listen to zoom level changes } }); From 6ac9d0e59aedd4ae4ed3d1a960a8bcfed3acf34a Mon Sep 17 00:00:00 2001 From: Dirk Baeumer Date: Tue, 10 May 2016 10:32:06 +0200 Subject: [PATCH 114/297] Fixes #6233: Support marker matches with startLine, startColumn and endColumn --- src/vs/platform/markers/common/problemMatcher.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/platform/markers/common/problemMatcher.ts b/src/vs/platform/markers/common/problemMatcher.ts index 5205d39a7cd..5be25f6865c 100644 --- a/src/vs/platform/markers/common/problemMatcher.ts +++ b/src/vs/platform/markers/common/problemMatcher.ts @@ -281,8 +281,8 @@ class AbstractLineMatcher implements ILineMatcher { } private createLocation(startLine: number, startColumn: number, endLine: number, endColumn: number): Location { - if (startLine && startColumn && endLine && endColumn) { - return { startLineNumber: startLine, startColumn: startColumn, endLineNumber: endLine, endColumn: endColumn }; + if (startLine && startColumn && endColumn) { + return { startLineNumber: startLine, startColumn: startColumn, endLineNumber: endLine || startLine, endColumn: endColumn }; } if (startLine && startColumn) { return { startLineNumber: startLine, startColumn: startColumn, endLineNumber: startLine, endColumn: startColumn }; From 6cc658cb72c145744a1bb84cf7d30068f465e9e1 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 9 May 2016 16:58:57 +0200 Subject: [PATCH 115/297] add concept of common properties to ctor options --- .../browser/standalone/standaloneServices.ts | 7 +- .../telemetry/browser/telemetryService.ts | 128 +++++++++++------- .../electronTelemetryService.ts | 106 +++++++-------- .../test/node/telemetryService.test.ts | 61 +++++---- src/vs/workbench/electron-browser/shell.ts | 14 +- .../test/browser/servicesTestUtils.ts | 1 - 6 files changed, 167 insertions(+), 150 deletions(-) diff --git a/src/vs/editor/browser/standalone/standaloneServices.ts b/src/vs/editor/browser/standalone/standaloneServices.ts index 53b3090a166..d8aabae64ba 100644 --- a/src/vs/editor/browser/standalone/standaloneServices.ts +++ b/src/vs/editor/browser/standalone/standaloneServices.ts @@ -27,7 +27,6 @@ import {IProgressService} from 'vs/platform/progress/common/progress'; import {IRequestService} from 'vs/platform/request/common/request'; import {ISearchService} from 'vs/platform/search/common/search'; import {IStorageService} from 'vs/platform/storage/common/storage'; -import {TelemetryService} from 'vs/platform/telemetry/browser/telemetryService'; import {ITelemetryService, NullTelemetryService} from 'vs/platform/telemetry/common/telemetry'; import {MainThreadService} from 'vs/platform/thread/common/mainThreadService'; import {IThreadService} from 'vs/platform/thread/common/thread'; @@ -163,11 +162,7 @@ export function getOrCreateStaticServices(services?: IEditorOverrideServices): I let telemetryService = services.telemetryService; if (!telemetryService) { - let config = contextService.getConfiguration(); - let enableTelemetry = config && config.env ? !!config.env.enableTelemetry: false; - telemetryService = enableTelemetry - ? new TelemetryService() - : NullTelemetryService; + telemetryService = NullTelemetryService; } let eventService = services.eventService || new EventService(); diff --git a/src/vs/platform/telemetry/browser/telemetryService.ts b/src/vs/platform/telemetry/browser/telemetryService.ts index f3a35929e09..8ae5e28bb82 100644 --- a/src/vs/platform/telemetry/browser/telemetryService.ts +++ b/src/vs/platform/telemetry/browser/telemetryService.ts @@ -8,23 +8,57 @@ import * as Platform from 'vs/base/common/platform'; import * as uuid from 'vs/base/common/uuid'; import {escapeRegExpCharacters} from 'vs/base/common/strings'; +import {IWorkspaceContextService, IEnvironment} from 'vs/platform/workspace/common/workspace'; import {ITelemetryService, ITelemetryAppender, ITelemetryInfo} from 'vs/platform/telemetry/common/telemetry'; import ErrorTelemetry from 'vs/platform/telemetry/common/errorTelemetry'; import {IdleMonitor, UserStatus} from 'vs/base/browser/idleMonitor'; import {TPromise} from 'vs/base/common/winjs.base'; import {IDisposable, dispose} from 'vs/base/common/lifecycle'; import {TimeKeeper, ITimerEvent} from 'vs/base/common/timer'; -import {withDefaults, cloneAndChange} from 'vs/base/common/objects'; +import {withDefaults, cloneAndChange, mixin} from 'vs/base/common/objects'; export interface ITelemetryServiceConfig { appender: ITelemetryAppender[]; + commonProperties?: TPromise<{ [name: string]: any }>[]; + piiPaths?: string[]; userOptIn?: boolean; enableHardIdle?: boolean; enableSoftIdle?: boolean; - commitHash?: string; - version?: string; - appRoot?: string; - extensionsRoot?: string; +} + +function createDefaultProperties(environment: IEnvironment): { [name: string]: any } { + + let seq = 0; + const startTime = Date.now(); + const sessionID = uuid.generateUuid() + Date.now(); + + let result = { + sessionID, + commitHash: environment.commitHash, + version: environment.version + }; + + // complex names and dynamic values + Object.defineProperties(result, { + 'timestamp': { + get: () => new Date(), + enumerable: true + }, + 'common.timesincesessionstart': { + get: () => Date.now() - startTime, + enumerable: true + }, + 'common.platform': { + get: () => Platform.Platform[Platform.platform], + enumerable: true + }, + 'common.sequence': { + get: () => seq++, + enumerable: true + } + }); + + return result; } export class TelemetryService implements ITelemetryService { @@ -33,40 +67,42 @@ export class TelemetryService implements ITelemetryService { public static SOFT_IDLE_TIME = 2 * 60 * 1000; public static IDLE_START_EVENT_NAME = 'UserIdleStart'; public static IDLE_STOP_EVENT_NAME = 'UserIdleStop'; - public static ERROR_FLUSH_TIMEOUT: number = 5 * 1000; public serviceId = ITelemetryService; - protected _telemetryInfo: ITelemetryInfo; protected _configuration: ITelemetryServiceConfig; protected _disposables: IDisposable[] = []; private _timeKeeper: TimeKeeper; private _hardIdleMonitor: IdleMonitor; private _softIdleMonitor: IdleMonitor; - private _eventCount = 0; - private _startTime = new Date(); - private _optInFriendly = ['optInStatus']; //holds a cache of predefined events that can be sent regardress of user optin status - private _cleanupPatterns: [RegExp, string][]= []; - constructor(config?: ITelemetryServiceConfig) { + private _commonProperties: TPromise<{ [name: string]: any }>; + private _cleanupPatterns: [RegExp, string][] = []; + + constructor( + config: ITelemetryServiceConfig, + @IWorkspaceContextService contextService: IWorkspaceContextService + ) { this._configuration = withDefaults(config, { appender: [], + commonProperties: [], + piiPaths: [], enableHardIdle: true, enableSoftIdle: true, userOptIn: true }); + this._commonProperties = TPromise.join(this._configuration.commonProperties) + .then(values => values.reduce((p, c) => mixin(p, c), createDefaultProperties(contextService.getConfiguration().env))); + // static cleanup patterns for: // #1 `file:///DANGEROUS/PATH/resources/app/Useful/Information` // #2 // Any other file path that doesn't match the approved form above should be cleaned. // #3 "Error: ENOENT; no such file or directory" is often followed with PII, clean it - if (this._configuration.appRoot) { - this._cleanupPatterns.push([new RegExp(escapeRegExpCharacters(this._configuration.appRoot), 'gi'), '']); - } - if (this._configuration.extensionsRoot) { - this._cleanupPatterns.push([new RegExp(escapeRegExpCharacters(this._configuration.extensionsRoot), 'gi'), '']); + for (let piiPath of this._configuration.piiPaths) { + this._cleanupPatterns.push([new RegExp(escapeRegExpCharacters(piiPath), 'gi'), '']); } this._cleanupPatterns.push( [/file:\/\/\/.*?\/resources\/app\//gi, ''], @@ -74,12 +110,6 @@ export class TelemetryService implements ITelemetryService { [/ENOENT: no such file or directory.*?\'([^\']+)\'/gi, 'ENOENT: no such file or directory'] ); - this._telemetryInfo = { - sessionId: uuid.generateUuid() + Date.now(), - instanceId: undefined, - machineId: undefined - }; - this._timeKeeper = new TimeKeeper(); this._disposables.push(this._timeKeeper); this._disposables.push(this._timeKeeper.addListener(events => this._onTelemetryTimerEventStop(events))); @@ -123,7 +153,14 @@ export class TelemetryService implements ITelemetryService { } public getTelemetryInfo(): TPromise { - return TPromise.as(this._telemetryInfo); + return this._commonProperties.then(values => { + // well known properties + let sessionId = values['sessionID']; + let instanceId = values['common.instanceId']; + let machineId = values['common.machineId']; + + return { sessionId, instanceId, machineId }; + }); } public dispose(): void { @@ -151,39 +188,30 @@ export class TelemetryService implements ITelemetryService { return; } - // don't send events when the user is optout unless the event is flaged as optin friendly - if (!this._configuration.userOptIn && this._optInFriendly.indexOf(eventName) === -1) { + // don't send events when the user is optout unless the event is the opt{in|out} signal + if (!this._configuration.userOptIn && eventName !== 'optInStatus') { return; } - this._eventCount++; - - if (!data) { - data = Object.create(null); - } - // (first) add common properties - let eventDate: Date = new Date(); - data['sessionID'] = this._telemetryInfo.sessionId; - data['timestamp'] = eventDate; - data['version'] = this._configuration.version; - data['commitHash'] = this._configuration.commitHash; - data['common.platform'] = Platform.Platform[Platform.platform]; - data['common.timesincesessionstart'] = (eventDate.getTime() - this._startTime.getTime()); - data['common.sequence'] = this._eventCount; - data['common.instanceId'] = this._telemetryInfo.instanceId; - data['common.machineId'] = this._telemetryInfo.machineId; + this._commonProperties.then(values => { - // (last) remove all PII from data - data = cloneAndChange(data, value => { - if (typeof value === 'string') { - return this._cleanupInfo(value); + data = mixin(data, values); + + // (last) remove all PII from data + data = cloneAndChange(data, value => { + if (typeof value === 'string') { + return this._cleanupInfo(value); + } + }); + + for (let appender of this._configuration.appender) { + appender.log(eventName, data); } - }); - for (let appender of this._configuration.appender) { - appender.log(eventName, data); - } + }).done(undefined, err => { + console.error(err); + }); } private _cleanupInfo(stack: string): string { diff --git a/src/vs/platform/telemetry/electron-browser/electronTelemetryService.ts b/src/vs/platform/telemetry/electron-browser/electronTelemetryService.ts index 5674dfd184c..c8869f4fd0d 100644 --- a/src/vs/platform/telemetry/electron-browser/electronTelemetryService.ts +++ b/src/vs/platform/telemetry/electron-browser/electronTelemetryService.ts @@ -11,10 +11,11 @@ import * as nls from 'vs/nls'; import * as errors from 'vs/base/common/errors'; import * as uuid from 'vs/base/common/uuid'; import {TelemetryService, ITelemetryServiceConfig} from 'vs/platform/telemetry/browser/telemetryService'; -import {ITelemetryService, ITelemetryInfo} from 'vs/platform/telemetry/common/telemetry'; +import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry'; import {IStorageService} from 'vs/platform/storage/common/storage'; -import {IConfigurationRegistry, Extensions} from 'vs/platform/configuration/common/configurationRegistry'; +import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace'; import {IConfigurationService} from 'vs/platform/configuration/common/configuration'; +import {IConfigurationRegistry, Extensions} from 'vs/platform/configuration/common/configurationRegistry'; import {Registry} from 'vs/platform/platform'; const TELEMETRY_SECTION_ID = 'telemetry'; @@ -24,73 +25,66 @@ namespace StorageKeys { export const InstanceId = 'telemetry.instanceId'; } +export function getDefaultProperties(storageService: IStorageService, contextService: IWorkspaceContextService): TPromise<{ [name: string]: string }> { + let result: { [name: string]: TPromise } = Object.create(null); + result['common.instanceId'] = getOrCreateInstanceId(storageService); + result['common.machineId'] = getOrCreateMachineId(storageService); + result['version'] = TPromise.as(contextService.getConfiguration().env.version); + result['commitHash'] = TPromise.as(contextService.getConfiguration().env.commitHash); + return TPromise.join(result); +} + +function getOrCreateInstanceId( storageService: IStorageService): TPromise { + let result = storageService.get(StorageKeys.InstanceId) || uuid.generateUuid(); + storageService.store(StorageKeys.InstanceId, result); + return TPromise.as(result); +} + +function getOrCreateMachineId(storageService: IStorageService): TPromise { + return new TPromise(resolve => { + let result = storageService.get(StorageKeys.MachineId); + if (result) { + return resolve(result); + } + // add a unique machine id as a hash of the macAddress + try { + getmac.getMac((error, macAddress) => { + if (!error) { + // crypt machine id + result = crypto.createHash('sha256').update(macAddress, 'utf8').digest('hex'); + } else { + result = uuid.generateUuid(); // fallback, generate a UUID + } + resolve(result); + }); + } catch (err) { + errors.onUnexpectedError(err); + resolve(uuid.generateUuid()); // fallback, generate a UUID + } + }).then(result => { + storageService.store(StorageKeys.MachineId, result); + return result; + }); +} + export class ElectronTelemetryService extends TelemetryService implements ITelemetryService { - private _telemetryInfoPromise: TPromise; - constructor( + configuration: ITelemetryServiceConfig, @IConfigurationService private _configurationService: IConfigurationService, - @IStorageService private _storageService: IStorageService, - configuration?: ITelemetryServiceConfig + @IWorkspaceContextService contextService:IWorkspaceContextService ) { - super(configuration); + super(configuration, contextService); - this._telemetryInfoPromise = this._setupTelemetryInfo(); this._updateUserOptIn(); this._configurationService.onDidUpdateConfiguration(this._updateUserOptIn, this, this._disposables); - this.publicLog('optInStatus', {optIn: this._configuration.userOptIn}); + this.publicLog('optInStatus', { optIn: this._configuration.userOptIn }); } - private _updateUserOptIn():void { + private _updateUserOptIn(): void { const config = this._configurationService.getConfiguration(TELEMETRY_SECTION_ID); this._configuration.userOptIn = config ? config.enableTelemetry : this._configuration.userOptIn; } - - public getTelemetryInfo(): TPromise { - return this._telemetryInfoPromise; - } - - private _setupTelemetryInfo(): TPromise { - - let instanceId: string, machineId: string; - - return new TPromise(resolve => { - // (1) instance identifier (from storage or fresh) - instanceId = this._storageService.get(StorageKeys.InstanceId) || uuid.generateUuid(); - this._storageService.store(StorageKeys.InstanceId, instanceId); - - // (2) machine identifier (from stroage or fresh) - machineId = this._storageService.get(StorageKeys.MachineId); - if (machineId) { - return resolve(this); - } - - // add a unique machine id as a hash of the macAddress - try { - getmac.getMac((error, macAddress) => { - if (!error) { - // crypt machine id - machineId = crypto.createHash('sha256').update(macAddress, 'utf8').digest('hex'); - } else { - machineId = uuid.generateUuid(); // fallback, generate a UUID - } - this._telemetryInfo.machineId = machineId; - this._storageService.store(StorageKeys.MachineId, machineId); - resolve(this); - }); - } catch (err) { - errors.onUnexpectedError(err); - machineId = uuid.generateUuid(); // fallback, generate a UUID - this._storageService.store(StorageKeys.MachineId, machineId); - resolve(this); - } - - }).then(() => { - this._telemetryInfo.instanceId = instanceId; - this._telemetryInfo.machineId = machineId; - return this._telemetryInfo; - }); - } } Registry.as(Extensions.Configuration).registerConfiguration({ diff --git a/src/vs/platform/telemetry/test/node/telemetryService.test.ts b/src/vs/platform/telemetry/test/node/telemetryService.test.ts index 5830589a817..09f5e465079 100644 --- a/src/vs/platform/telemetry/test/node/telemetryService.test.ts +++ b/src/vs/platform/telemetry/test/node/telemetryService.test.ts @@ -8,6 +8,7 @@ import * as assert from 'assert'; import IdleMonitor = require('vs/base/browser/idleMonitor'); import {TelemetryService} from 'vs/platform/telemetry/browser/telemetryService'; import Telemetry = require('vs/platform/telemetry/common/telemetry'); +import {TestContextService} from 'vs/workbench/test/browser/servicesTestUtils'; import Errors = require('vs/base/common/errors'); import Timer = require('vs/base/common/timer'); import * as sinon from 'sinon'; @@ -89,7 +90,7 @@ suite('TelemetryService', () => { // Appenders test('No appenders', sinon.test(function() { - let service = new AppenderCountTelemetryService(); + let service = new AppenderCountTelemetryService(undefined, new TestContextService()); assert.equal(service.getAppendersCount(), 0); // log events @@ -103,7 +104,7 @@ suite('TelemetryService', () => { test('Disposing', sinon.test(function() { let testAppender = new TestTelemetryAppender(); - let service = new TelemetryService({ appender: [testAppender] }); + let service = new TelemetryService({ appender: [testAppender] }, new TestContextService()); service.publicLog('testPrivateEvent'); assert.equal(testAppender.getEventsCount(), 1); @@ -115,7 +116,7 @@ suite('TelemetryService', () => { // event reporting test('Simple event', sinon.test(function() { let testAppender = new TestTelemetryAppender(); - let service = new TelemetryService({ appender: [testAppender] }); + let service = new TelemetryService({ appender: [testAppender] }, new TestContextService()); return service.getTelemetryInfo().then(info => { @@ -133,23 +134,25 @@ suite('TelemetryService', () => { test('default properties', function () { let testAppender = new TestTelemetryAppender(); - let service = new TelemetryService({ appender: [testAppender] }); + let service = new TelemetryService({ appender: [testAppender] }, new TestContextService()); return service.getTelemetryInfo().then(info => { service.publicLog('testEvent'); let [first] = testAppender.events; - assert.equal(Object.keys(first.data).length, 9); - assert.ok('sessionID' in first.data); - assert.ok('timestamp' in first.data); + assert.equal(Object.keys(first.data).length, 7); assert.ok('version' in first.data); assert.ok('commitHash' in first.data); + assert.ok('sessionID' in first.data); + assert.ok('timestamp' in first.data); assert.ok('common.platform' in first.data); assert.ok('common.timesincesessionstart' in first.data); assert.ok('common.sequence' in first.data); - assert.ok('common.instanceId' in first.data); - assert.ok('common.machineId' in first.data); + + // assert.equal(Object.keys(first.data).length, 9); + // assert.ok('common.instanceId' in first.data); + // assert.ok('common.machineId' in first.data); service.dispose(); }); @@ -157,7 +160,7 @@ suite('TelemetryService', () => { test('Event with data', sinon.test(function() { let testAppender = new TestTelemetryAppender(); - let service = new TelemetryService({ appender: [testAppender] }); + let service = new TelemetryService({ appender: [testAppender] }, new TestContextService()); return service.getTelemetryInfo().then(info => { @@ -188,7 +191,7 @@ suite('TelemetryService', () => { Timer.ENABLE_TIMER = true; let testAppender = new TestTelemetryAppender(); - let service = new TelemetryService({ appender: [testAppender] }); + let service = new TelemetryService({ appender: [testAppender] }, new TestContextService()); let t1 = service.timedPublicLog('editorDance'); this.clock.tick(20); @@ -220,7 +223,7 @@ suite('TelemetryService', () => { test('enableTelemetry on by default', sinon.test(function() { let testAppender = new TestTelemetryAppender(); - let service = new TelemetryService({ appender: [testAppender] }); + let service = new TelemetryService({ appender: [testAppender] }, new TestContextService()); service.publicLog('testEvent'); assert.equal(testAppender.getEventsCount(), 1); @@ -236,7 +239,7 @@ suite('TelemetryService', () => { try { let testAppender = new TestTelemetryAppender(); - let service = new TelemetryService({ appender: [testAppender] }); + let service = new TelemetryService({ appender: [testAppender] }, new TestContextService()); let e: any = new Error('This is a test.'); @@ -290,7 +293,7 @@ suite('TelemetryService', () => { let errorStub = this.stub(window, 'onerror'); let testAppender = new TestTelemetryAppender(); - let service = new TelemetryService({ appender: [testAppender] }); + let service = new TelemetryService({ appender: [testAppender] }, new TestContextService()); let testError = new Error('test'); (window.onerror)('Error Message', 'file.js', 2, 42, testError); @@ -314,7 +317,7 @@ suite('TelemetryService', () => { let errorStub = this.stub(window, 'onerror'); let settings = new ErrorTestingSettings(); let testAppender = new TestTelemetryAppender(); - let service = new TelemetryService({ appender: [testAppender] }); + let service = new TelemetryService({ appender: [testAppender] }, new TestContextService()); let dangerousFilenameError: any = new Error('dangerousFilename'); dangerousFilenameError.stack = settings.stack; @@ -342,7 +345,7 @@ suite('TelemetryService', () => { try { let settings = new ErrorTestingSettings(); let testAppender = new TestTelemetryAppender(); - let service = new TelemetryService({ appender: [testAppender] }); + let service = new TelemetryService({ appender: [testAppender] }, new TestContextService()); let dangerousPathWithoutImportantInfoError: any = new Error(settings.dangerousPathWithoutImportantInfo); dangerousPathWithoutImportantInfoError.stack = settings.stack; @@ -368,7 +371,7 @@ suite('TelemetryService', () => { let errorStub = this.stub(window, 'onerror'); let settings = new ErrorTestingSettings(); let testAppender = new TestTelemetryAppender(); - let service = new TelemetryService({ appender: [testAppender] }); + let service = new TelemetryService({ appender: [testAppender] }, new TestContextService()); let dangerousPathWithoutImportantInfoError: any = new Error('dangerousPathWithoutImportantInfo'); dangerousPathWithoutImportantInfoError.stack = settings.stack; @@ -395,7 +398,7 @@ suite('TelemetryService', () => { try { let settings = new ErrorTestingSettings(); let testAppender = new TestTelemetryAppender(); - let service = new TelemetryService({ appender: [testAppender] }); + let service = new TelemetryService({ appender: [testAppender] }, new TestContextService()); let dangerousPathWithImportantInfoError: any = new Error(settings.dangerousPathWithImportantInfo); dangerousPathWithImportantInfoError.stack = settings.stack; @@ -424,7 +427,7 @@ suite('TelemetryService', () => { let errorStub = this.stub(window, 'onerror'); let settings = new ErrorTestingSettings(); let testAppender = new TestTelemetryAppender(); - let service = new TelemetryService({ appender: [testAppender] }); + let service = new TelemetryService({ appender: [testAppender] }, new TestContextService()); let dangerousPathWithImportantInfoError: any = new Error('dangerousPathWithImportantInfo'); dangerousPathWithImportantInfoError.stack = settings.stack; @@ -453,7 +456,7 @@ suite('TelemetryService', () => { try { let settings = new ErrorTestingSettings(); let testAppender = new TestTelemetryAppender(); - let service = new TelemetryService({ appender: [testAppender] }); + let service = new TelemetryService({ appender: [testAppender] }, new TestContextService()); let missingModelError: any = new Error(settings.missingModelMessage); missingModelError.stack = settings.stack; @@ -482,7 +485,7 @@ suite('TelemetryService', () => { let errorStub = this.stub(window, 'onerror'); let settings = new ErrorTestingSettings(); let testAppender = new TestTelemetryAppender(); - let service = new TelemetryService({ appender: [testAppender] }); + let service = new TelemetryService({ appender: [testAppender] }, new TestContextService()); let missingModelError: any = new Error('missingModelMessage'); missingModelError.stack = settings.stack; @@ -512,7 +515,7 @@ suite('TelemetryService', () => { try { let settings = new ErrorTestingSettings(); let testAppender = new TestTelemetryAppender(); - let service = new TelemetryService({ appender: [testAppender] }); + let service = new TelemetryService({ appender: [testAppender] }, new TestContextService()); let noSuchFileError: any = new Error(settings.noSuchFileMessage); noSuchFileError.stack = settings.stack; @@ -545,7 +548,7 @@ suite('TelemetryService', () => { let errorStub = this.stub(window, 'onerror'); let settings = new ErrorTestingSettings(); let testAppender = new TestTelemetryAppender(); - let service = new TelemetryService({ appender: [testAppender] }); + let service = new TelemetryService({ appender: [testAppender] }, new TestContextService()); let noSuchFileError: any = new Error('noSuchFileMessage'); noSuchFileError.stack = settings.stack; @@ -574,7 +577,7 @@ suite('TelemetryService', () => { test('Test hard idle does not affect sending normal events in active state', sinon.test(function() { let testAppender = new TestTelemetryAppender(); - let service = new TelemetryService({ enableHardIdle: true, enableSoftIdle: false, appender: [testAppender] }); + let service = new TelemetryService({ enableHardIdle: true, enableSoftIdle: false, appender: [testAppender] }, new TestContextService()); //report an event @@ -590,7 +593,7 @@ suite('TelemetryService', () => { test('Test hard idle stops events from being sent in idle state', sinon.test(function() { let testAppender = new TestTelemetryAppender(); - let service = new TelemetryService({ enableHardIdle: true, enableSoftIdle: false, appender: [testAppender] }); + let service = new TelemetryService({ enableHardIdle: true, enableSoftIdle: false, appender: [testAppender] }, new TestContextService()); // make the user idle this.clock.tick(IdleMonitor.DEFAULT_IDLE_TIME); @@ -628,7 +631,7 @@ suite('TelemetryService', () => { this.stub(IdleMonitor, 'IdleMonitor', MockIdleMonitor); let testAppender = new TestTelemetryAppender(); - let service = new TelemetryService({ enableHardIdle: false, enableSoftIdle: true, appender: [testAppender] }); + let service = new TelemetryService({ enableHardIdle: false, enableSoftIdle: true, appender: [testAppender] }, new TestContextService()); assert.equal(testAppender.getEventsCount(), 0); @@ -652,7 +655,7 @@ suite('TelemetryService', () => { test('Telemetry Service respects user opt-in settings', sinon.test(function() { let testAppender = new TestTelemetryAppender(); - let service = new TelemetryService({userOptIn: false, appender: [testAppender] }); + let service = new TelemetryService({userOptIn: false, appender: [testAppender] }, new TestContextService()); service.publicLog('testEvent'); assert.equal(testAppender.getEventsCount(), 0); @@ -662,7 +665,7 @@ suite('TelemetryService', () => { test('Telemetry Service sends events when enableTelemetry is on even user optin is on', sinon.test(function() { let testAppender = new TestTelemetryAppender(); - let service = new TelemetryService({userOptIn: true, appender: [testAppender] }); + let service = new TelemetryService({userOptIn: true, appender: [testAppender] }, new TestContextService()); service.publicLog('testEvent'); assert.equal(testAppender.getEventsCount(), 1); @@ -672,7 +675,7 @@ suite('TelemetryService', () => { test('Telemetry Service allows optin friendly events', sinon.test(function() { let testAppender = new TestTelemetryAppender(); - let service = new TelemetryService({userOptIn: false, appender: [testAppender] }); + let service = new TelemetryService({userOptIn: false, appender: [testAppender] }, new TestContextService()); service.publicLog('testEvent'); assert.equal(testAppender.getEventsCount(), 0); diff --git a/src/vs/workbench/electron-browser/shell.ts b/src/vs/workbench/electron-browser/shell.ts index 06269ed1488..2cdbf8a7f6c 100644 --- a/src/vs/workbench/electron-browser/shell.ts +++ b/src/vs/workbench/electron-browser/shell.ts @@ -20,7 +20,7 @@ import timer = require('vs/base/common/timer'); import {Workbench} from 'vs/workbench/browser/workbench'; import {Storage, inMemoryLocalStorageInstance} from 'vs/workbench/common/storage'; import {ITelemetryService, NullTelemetryService} from 'vs/platform/telemetry/common/telemetry'; -import {ElectronTelemetryService} from 'vs/platform/telemetry/electron-browser/electronTelemetryService'; +import {ElectronTelemetryService, getDefaultProperties} from 'vs/platform/telemetry/electron-browser/electronTelemetryService'; import {AppInsightsAppender} from 'vs/platform/telemetry/node/appInsightsAppender'; import {ElectronIntegration} from 'vs/workbench/electron-browser/integration'; import {Update} from 'vs/workbench/electron-browser/update'; @@ -204,13 +204,11 @@ export class WorkbenchShell { this.storageService = new Storage(this.contextService, window.localStorage, disableWorkspaceStorage ? inMemoryLocalStorageInstance : window.localStorage); if (this.configuration.env.isBuilt && !this.configuration.env.extensionDevelopmentPath && !!this.configuration.env.enableTelemetry) { - this.telemetryService = new ElectronTelemetryService(this.configurationService, this.storageService, { - appRoot: this.configuration.env.appRoot, - extensionsRoot: this.configuration.env.userExtensionsHome, - version: this.configuration.env.version, - commitHash: this.configuration.env.commitHash, - appender: [new AppInsightsAppender(this.storageService, this.configuration.env.aiConfig)] - }); + this.telemetryService = new ElectronTelemetryService({ + appender: [new AppInsightsAppender(this.storageService, this.configuration.env.aiConfig)], + commonProperties: [getDefaultProperties(this.storageService, this.contextService)], + piiPaths: [this.configuration.env.appRoot, this.configuration.env.userExtensionsHome] + }, this.configurationService, this.contextService); } else { this.telemetryService = NullTelemetryService; } diff --git a/src/vs/workbench/test/browser/servicesTestUtils.ts b/src/vs/workbench/test/browser/servicesTestUtils.ts index 8d1bfe4307d..90d81ffaf88 100644 --- a/src/vs/workbench/test/browser/servicesTestUtils.ts +++ b/src/vs/workbench/test/browser/servicesTestUtils.ts @@ -27,7 +27,6 @@ import {IEditorInput, IEditorModel, Position, IEditor, IResourceInput, ITextEdit import {IEventService} from 'vs/platform/event/common/event'; import {IUntitledEditorService} from 'vs/workbench/services/untitled/common/untitledEditorService'; import {IMessageService, IConfirmation} from 'vs/platform/message/common/message'; -import Lifecycle = require('vs/base/common/lifecycle'); import {BaseRequestService} from 'vs/platform/request/common/baseRequestService'; import {IWorkspace, IConfiguration} from 'vs/platform/workspace/common/workspace'; From a5c88e7ac071d4138a71e8f0a9eab9115791be12 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 9 May 2016 17:51:31 +0200 Subject: [PATCH 116/297] move common properties that require nodejs into electronTelemetryService and out of appender, enables #1000 --- .../electronTelemetryService.ts | 86 +++++++++++- .../telemetry/node/appInsightsAppender.ts | 127 +----------------- .../test/node/appInsightsAppender.test.ts | 78 +++-------- .../test/node/defaultProperties.test.ts | 47 +++++++ src/vs/workbench/electron-browser/shell.ts | 4 +- 5 files changed, 158 insertions(+), 184 deletions(-) create mode 100644 src/vs/platform/telemetry/test/node/defaultProperties.test.ts diff --git a/src/vs/platform/telemetry/electron-browser/electronTelemetryService.ts b/src/vs/platform/telemetry/electron-browser/electronTelemetryService.ts index c8869f4fd0d..9345f9d225a 100644 --- a/src/vs/platform/telemetry/electron-browser/electronTelemetryService.ts +++ b/src/vs/platform/telemetry/electron-browser/electronTelemetryService.ts @@ -5,7 +5,8 @@ import getmac = require('getmac'); import crypto = require('crypto'); - +import winreg = require('winreg'); +import os = require('os'); import { TPromise } from 'vs/base/common/winjs.base'; import * as nls from 'vs/nls'; import * as errors from 'vs/base/common/errors'; @@ -23,14 +24,38 @@ const TELEMETRY_SECTION_ID = 'telemetry'; namespace StorageKeys { export const MachineId = 'telemetry.machineId'; export const InstanceId = 'telemetry.instanceId'; + export const sqmUserId: string = 'telemetry.sqm.userId'; + export const sqmMachineId: string = 'telemetry.sqm.machineId'; + export const lastSessionDate: string = 'telemetry.lastSessionDate'; + export const firstSessionDate: string = 'telemetry.firstSessionDate'; + export const SQM_KEY: string = '\\Software\\Microsoft\\SQMClient'; } -export function getDefaultProperties(storageService: IStorageService, contextService: IWorkspaceContextService): TPromise<{ [name: string]: string }> { - let result: { [name: string]: TPromise } = Object.create(null); +export function getDefaultProperties(storageService: IStorageService): TPromise<{ [name: string]: string }> { + let result: { [name: string]: any } = Object.create(null); + + // add shell & render version + result['common.version.shell'] = process.versions && (process).versions['electron']; + result['common.version.renderer'] = process.versions && (process).versions['chrome']; + result['common.osVersion'] = os.release(); + + // session dates, first, last, isNewSession + const lastSessionDate = storageService.get(StorageKeys.lastSessionDate); + const firstSessionDate = storageService.get(StorageKeys.firstSessionDate) || new Date().toUTCString(); + storageService.store(StorageKeys.firstSessionDate, firstSessionDate); + storageService.store(StorageKeys.lastSessionDate, new Date().toUTCString()); + result['common.firstSessionDate'] = firstSessionDate; + result['common.lastSessionDate'] = lastSessionDate; + result['common.isNewSession'] = !lastSessionDate ? 1 : 0; + + // promise based properties result['common.instanceId'] = getOrCreateInstanceId(storageService); result['common.machineId'] = getOrCreateMachineId(storageService); - result['version'] = TPromise.as(contextService.getConfiguration().env.version); - result['commitHash'] = TPromise.as(contextService.getConfiguration().env.commitHash); + if (process.platform === 'win32') { + result['common.sqm.userid'] = getSqmUserId(storageService); + result['common.sqm.machineid'] = getSqmMachineId(storageService); + } + return TPromise.join(result); } @@ -67,6 +92,57 @@ function getOrCreateMachineId(storageService: IStorageService): TPromise }); } +function getSqmUserId(storageService: IStorageService): TPromise { + var sqmUserId = storageService.get(StorageKeys.sqmUserId); + if (sqmUserId) { + return TPromise.as(sqmUserId); + } + return getWinRegKeyData(StorageKeys.SQM_KEY, 'UserId', winreg.HKCU).then(result => { + if (result) { + storageService.store(StorageKeys.sqmUserId, result); + return result; + } + }); +} + +function getSqmMachineId(storageService: IStorageService): TPromise { + let sqmMachineId = storageService.get(StorageKeys.sqmMachineId); + if (sqmMachineId) { + return TPromise.as(sqmMachineId); + } + return getWinRegKeyData(StorageKeys.SQM_KEY, 'MachineId', winreg.HKLM).then(result => { + if (result) { + storageService.store(StorageKeys.sqmMachineId, result); + return result; + } + }); +} + +function getWinRegKeyData(key: string, name: string, hive: string): TPromise { + return new TPromise((resolve, reject) => { + if (process.platform === 'win32') { + try { + var reg = new winreg({ hive, key }); + reg.get(name, (e, result) => { + if (e || !result) { + reject(null); + } else { + resolve(result.value); + } + }); + } catch (err) { + errors.onUnexpectedError(err); + reject(err); + } + } else { + resolve(null); + } + }).then(undefined, err => { + // we only want success + return undefined; + }); +} + export class ElectronTelemetryService extends TelemetryService implements ITelemetryService { constructor( diff --git a/src/vs/platform/telemetry/node/appInsightsAppender.ts b/src/vs/platform/telemetry/node/appInsightsAppender.ts index 18f73cb40e7..bc44e6bd618 100644 --- a/src/vs/platform/telemetry/node/appInsightsAppender.ts +++ b/src/vs/platform/telemetry/node/appInsightsAppender.ts @@ -4,36 +4,17 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import errors = require('vs/base/common/errors'); -import {TPromise} from 'vs/base/common/winjs.base'; -import {mixin} from 'vs/base/common/objects'; -import {IStorageService} from 'vs/platform/storage/common/storage'; import {ITelemetryAppender} from 'vs/platform/telemetry/common/telemetry'; import {AIAdapter, IAIAdapter} from 'vs/base/node/aiAdapter'; -import winreg = require('winreg'); -import os = require('os'); - -export namespace StorageKeys { - export const sqmUserId: string = 'telemetry.sqm.userId'; - export const sqmMachineId: string = 'telemetry.sqm.machineId'; - export const lastSessionDate: string = 'telemetry.lastSessionDate'; - export const firstSessionDate: string = 'telemetry.firstSessionDate'; -} export class AppInsightsAppender implements ITelemetryAppender { private static EVENT_NAME_PREFIX: string = 'monacoworkbench'; - private static SQM_KEY: string = '\\Software\\Microsoft\\SQMClient'; private appInsights: IAIAdapter; private appInsightsVortex: IAIAdapter; - private _additionalProperties: TPromise<{ [key: string]: any }>; - constructor( - @IStorageService storageService: IStorageService, - config: {key: string; asimovKey: string}, - _testing_client?: IAIAdapter - ) { + constructor(config: { key: string; asimovKey: string }, _testing_client?: IAIAdapter) { let {key, asimovKey} = config; if (_testing_client) { // for test @@ -49,109 +30,15 @@ export class AppInsightsAppender implements ITelemetryAppender { this.appInsightsVortex = new AIAdapter(AppInsightsAppender.EVENT_NAME_PREFIX, undefined, asimovKey); } } - - this._additionalProperties = AppInsightsAppender._loadAddtionalProperties(storageService); } - private static _loadAddtionalProperties(storageService: IStorageService): TPromise<{ [key: string]: any }> { - - const result: { [key: string]: any } = Object.create(null); - let promises: TPromise[] = []; - - // add shell & render version - if (process.versions) { - result['common.version.shell'] = (process).versions['electron']; - result['common.version.renderer'] = (process).versions['chrome']; + public log(eventName: string, data: any = Object.create(null)): void { + if (this.appInsights) { + this.appInsights.log(eventName, data); } - - // add SQM data for windows machines - if (process.platform === 'win32') { - var sqmUserId = storageService.get(StorageKeys.sqmUserId); - if (sqmUserId) { - result['common.sqm.userid'] = sqmUserId; - } else { - promises.push(AppInsightsAppender._getWinRegKeyData(AppInsightsAppender.SQM_KEY, 'UserId', winreg.HKCU).then(result => { - if (result) { - result['common.sqm.userid'] = result; - storageService.store(StorageKeys.sqmUserId, result); - } - })); - } - - var sqmMachineId = storageService.get(StorageKeys.sqmMachineId); - if (sqmMachineId) { - result['common.sqm.machineid'] = sqmMachineId; - } - else { - promises.push(AppInsightsAppender._getWinRegKeyData(AppInsightsAppender.SQM_KEY, 'MachineId', winreg.HKLM).then(result => { - if (result) { - result['common.sqm.machineid'] = result; - storageService.store(StorageKeys.sqmMachineId, result); - } - })); - } + if (this.appInsightsVortex) { + this.appInsightsVortex.log(eventName, data); } - - var firstSessionDate = storageService.get(StorageKeys.firstSessionDate); - if (!firstSessionDate) { - firstSessionDate = (new Date()).toUTCString(); - storageService.store(StorageKeys.firstSessionDate, firstSessionDate); - } - result['common.firstSessionDate'] = firstSessionDate; - - //report last session date and isNewSession flag - var lastSessionDate = storageService.get(StorageKeys.lastSessionDate); - if (!lastSessionDate) { - result['common.isNewSession'] = 1; - } else { - result['common.isNewSession'] = 0; - result['common.lastSessionDate'] = lastSessionDate; - } - - storageService.store(StorageKeys.lastSessionDate, (new Date()).toUTCString()); - - if (os) { - result['common.osVersion'] = os.release(); - } - - return TPromise.join(promises).then(() => result, () => result); - } - - private static _getWinRegKeyData(key: string, name: string, hive: string): TPromise { - return new TPromise((resolve, reject) => { - if (process.platform === 'win32') { - try { - var reg = new winreg({ hive, key }); - reg.get(name, (e, result) => { - if (e || !result) { - reject(null); - } else { - resolve(result.value); - } - }); - } catch (err) { - errors.onUnexpectedError(err); - reject(err); - } - } else { - resolve(null); - } - }).then(undefined, err => { - // we only want success - return undefined; - }); - } - - public log(eventName: string, data?: any): TPromise { - return this._additionalProperties.then(additionalProperties => { - data = mixin(data, additionalProperties); - if (this.appInsights) { - this.appInsights.log(eventName, data); - } - if (this.appInsightsVortex) { - this.appInsightsVortex.log(eventName, data); - } - }); } public dispose(): void { @@ -164,4 +51,4 @@ export class AppInsightsAppender implements ITelemetryAppender { this.appInsights = null; this.appInsightsVortex = null; } -} \ No newline at end of file +} diff --git a/src/vs/platform/telemetry/test/node/appInsightsAppender.test.ts b/src/vs/platform/telemetry/test/node/appInsightsAppender.test.ts index efbb6b52081..7f4f3074a66 100644 --- a/src/vs/platform/telemetry/test/node/appInsightsAppender.test.ts +++ b/src/vs/platform/telemetry/test/node/appInsightsAppender.test.ts @@ -6,8 +6,7 @@ import * as assert from 'assert'; import {IAIAdapter} from 'vs/base/node/aiAdapter'; -import {AppInsightsAppender, StorageKeys} from 'vs/platform/telemetry/node/appInsightsAppender'; -import {TestStorageService} from 'vs/workbench/test/browser/servicesTestUtils'; +import {AppInsightsAppender} from 'vs/platform/telemetry/node/appInsightsAppender'; interface IAppInsightsEvent { eventName: string; @@ -16,16 +15,16 @@ interface IAppInsightsEvent { class AIAdapterMock implements IAIAdapter { - public events: IAppInsightsEvent[]=[]; + public events: IAppInsightsEvent[] = []; public IsTrackingPageView: boolean = false; - public exceptions: any[] =[]; + public exceptions: any[] = []; constructor(private prefix: string) { } public log(eventName: string, data?: any): void { this.events.push({ - eventName: this.prefix+'/'+eventName, + eventName: this.prefix + '/' + eventName, data: data }); } @@ -44,7 +43,7 @@ suite('Telemetry - AppInsightsTelemetryAppender', () => { setup(() => { appInsightsMock = new AIAdapterMock('testPrefix'); - appender = new AppInsightsAppender(new TestStorageService(), { key: '123', asimovKey: undefined }, appInsightsMock); + appender = new AppInsightsAppender({ key: '123', asimovKey: undefined }, appInsightsMock); }); teardown(() => { @@ -52,67 +51,32 @@ suite('Telemetry - AppInsightsTelemetryAppender', () => { }); test('Simple event', () => { - return appender.log('testEvent').then(_ => { - assert.equal(appInsightsMock.events.length, 1); - assert.equal(appInsightsMock.events[0].eventName, 'testPrefix/testEvent'); - }); - }); - - test('test additional properties', () => { - return appender.log('testEvent').then(_ => { - assert.equal(appInsightsMock.events.length, 1); - - let [first] = appInsightsMock.events; - assert.equal(first.eventName, 'testPrefix/testEvent'); - assert.ok('common.osVersion' in first.data); - assert.ok('common.isNewSession' in first.data); - assert.ok('common.firstSessionDate' in first.data); - assert.ok(!('common.lastSessionDate' in first.data)); // conditional, see below - // assert.ok('common.version.shell' in first.data); // only when running on electron - // assert.ok('common.version.renderer' in first.data); - // TODO@Joh: This is not always there... - // if (process.platform === 'win32') { // SQM only on windows - // assert.ok('common.sqm.userid' in first.data); - // assert.ok('common.sqm.machineid' in first.data); - // } - }); - }); - - test('test additional properties with storage data', () => { - const storage = new TestStorageService(); - storage.store(StorageKeys.lastSessionDate, 'somevalue'); - let appender = new AppInsightsAppender(storage, { key: '123', asimovKey: undefined }, appInsightsMock); - return appender.log('testEvent').then(_ => { - let [first] = appInsightsMock.events; - assert.ok('common.lastSessionDate' in first.data); // conditional - appender.dispose(); - }); + appender.log('testEvent'); + assert.equal(appInsightsMock.events.length, 1); + assert.equal(appInsightsMock.events[0].eventName, 'testPrefix/testEvent'); }); test('Event with data', () => { - return appender.log('testEvent', { + appender.log('testEvent', { title: 'some title', width: 100, height: 200 - }).then(_ => { - assert.equal(appInsightsMock.events.length, 1); - assert.equal(appInsightsMock.events[0].eventName, 'testPrefix/testEvent'); - - assert.equal(appInsightsMock.events[0].data['title'], 'some title'); - assert.equal(appInsightsMock.events[0].data['width'], 100); - assert.equal(appInsightsMock.events[0].data['height'], 200); }); + assert.equal(appInsightsMock.events.length, 1); + assert.equal(appInsightsMock.events[0].eventName, 'testPrefix/testEvent'); + + assert.equal(appInsightsMock.events[0].data['title'], 'some title'); + assert.equal(appInsightsMock.events[0].data['width'], 100); + assert.equal(appInsightsMock.events[0].data['height'], 200); }); test('Test asimov', () => { - appender = new AppInsightsAppender(new TestStorageService(), { key: '123', asimovKey: 'AIF-123' }, appInsightsMock); + appender = new AppInsightsAppender({ key: '123', asimovKey: 'AIF-123' }, appInsightsMock); + appender.log('testEvent'); + assert.equal(appInsightsMock.events.length, 2); + assert.equal(appInsightsMock.events[0].eventName, 'testPrefix/testEvent'); - return appender.log('testEvent').then(_ => { - assert.equal(appInsightsMock.events.length, 2); - assert.equal(appInsightsMock.events[0].eventName, 'testPrefix/testEvent'); - - // test vortex - assert.equal(appInsightsMock.events[1].eventName, 'testPrefix/testEvent'); - }); + // test vortex + assert.equal(appInsightsMock.events[1].eventName, 'testPrefix/testEvent'); }); }); \ No newline at end of file diff --git a/src/vs/platform/telemetry/test/node/defaultProperties.test.ts b/src/vs/platform/telemetry/test/node/defaultProperties.test.ts new file mode 100644 index 00000000000..953ba6f11e4 --- /dev/null +++ b/src/vs/platform/telemetry/test/node/defaultProperties.test.ts @@ -0,0 +1,47 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +import * as assert from 'assert'; +import {getDefaultProperties} from 'vs/platform/telemetry/electron-browser/electronTelemetryService'; +import {TestStorageService} from 'vs/workbench/test/browser/servicesTestUtils'; + +suite('Telemetry - common properties', function () { + + test('getDefaultProperties', function () { + + return getDefaultProperties(new TestStorageService()).then(props => { + + // assert.ok('common.version.shell' in first.data); // only when running on electron + // assert.ok('common.version.renderer' in first.data); + assert.ok('common.osVersion' in props, 'osVersion'); + + assert.ok('common.firstSessionDate' in props, 'firstSessionDate'); + assert.ok(!('common.lastSessionDate' in props), 'lastSessionDate'); // conditional, see bel, 'lastSessionDate'ow + assert.ok('common.isNewSession' in props, 'isNewSession'); + + // machine id et al + assert.ok('common.instanceId' in props, 'instanceId'); + assert.ok('common.machineId' in props, 'machineId'); + if (process.platform === 'win32') { // SQM only on windows + assert.ok('common.sqm.userid' in props, 'userid'); + assert.ok('common.sqm.machineid' in props, 'machineid'); + } + }); + }); + + test('getDefaultProperties, lastSessionDate when aviablale', function () { + + let service = new TestStorageService(); + service.store('telemetry.lastSessionDate', new Date().toUTCString()); + + return getDefaultProperties(service).then(props => { + + assert.ok('common.lastSessionDate' in props); // conditional, see below + assert.ok('common.isNewSession' in props); + assert.equal(props['common.isNewSession'], 0); + }); + }); +}); diff --git a/src/vs/workbench/electron-browser/shell.ts b/src/vs/workbench/electron-browser/shell.ts index 2cdbf8a7f6c..907f822252d 100644 --- a/src/vs/workbench/electron-browser/shell.ts +++ b/src/vs/workbench/electron-browser/shell.ts @@ -205,8 +205,8 @@ export class WorkbenchShell { if (this.configuration.env.isBuilt && !this.configuration.env.extensionDevelopmentPath && !!this.configuration.env.enableTelemetry) { this.telemetryService = new ElectronTelemetryService({ - appender: [new AppInsightsAppender(this.storageService, this.configuration.env.aiConfig)], - commonProperties: [getDefaultProperties(this.storageService, this.contextService)], + appender: [new AppInsightsAppender(this.configuration.env.aiConfig)], + commonProperties: [getDefaultProperties(this.storageService)], piiPaths: [this.configuration.env.appRoot, this.configuration.env.userExtensionsHome] }, this.configurationService, this.contextService); } else { From 3f60a259d1d8abc333ebf838077ce844d521aae2 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 10 May 2016 08:30:05 +0200 Subject: [PATCH 117/297] fix #6212 --- src/vs/base/node/aiAdapter.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/vs/base/node/aiAdapter.ts b/src/vs/base/node/aiAdapter.ts index 850f255ffdb..495b942601d 100644 --- a/src/vs/base/node/aiAdapter.ts +++ b/src/vs/base/node/aiAdapter.ts @@ -157,8 +157,11 @@ export class AIAdapter implements IAIAdapter { } public dispose(): void { - this._aiClient.sendPendingData(() => { - // all data flushed - }); + if (this._aiClient) { + this._aiClient.sendPendingData(() => { + // all data flushed + this._aiClient = undefined; + }); + } } } \ No newline at end of file From 5b4adc72a2d413fa496b83a711a654595579930b Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 10 May 2016 10:41:23 +0200 Subject: [PATCH 118/297] remove electron telemetry service, move optin logic to telemetry service, introduce commonProperties.ts for *all* common properties, tests!, getting closer to #1000 --- .../telemetry/browser/telemetryService.ts | 110 +++--- src/vs/platform/telemetry/common/telemetry.ts | 2 +- .../commonProperties.ts} | 93 +++-- .../test/node/commonProperties.test.ts | 76 +++++ .../test/node/defaultProperties.test.ts | 47 --- .../test/node/telemetryService.test.ts | 320 ++++++++++-------- src/vs/workbench/electron-browser/shell.ts | 9 +- 7 files changed, 351 insertions(+), 306 deletions(-) rename src/vs/platform/telemetry/{electron-browser/electronTelemetryService.ts => node/commonProperties.ts} (65%) create mode 100644 src/vs/platform/telemetry/test/node/commonProperties.test.ts delete mode 100644 src/vs/platform/telemetry/test/node/defaultProperties.test.ts diff --git a/src/vs/platform/telemetry/browser/telemetryService.ts b/src/vs/platform/telemetry/browser/telemetryService.ts index 8ae5e28bb82..16b52fb6ff4 100644 --- a/src/vs/platform/telemetry/browser/telemetryService.ts +++ b/src/vs/platform/telemetry/browser/telemetryService.ts @@ -5,62 +5,29 @@ 'use strict'; -import * as Platform from 'vs/base/common/platform'; -import * as uuid from 'vs/base/common/uuid'; +import {localize} from 'vs/nls'; import {escapeRegExpCharacters} from 'vs/base/common/strings'; -import {IWorkspaceContextService, IEnvironment} from 'vs/platform/workspace/common/workspace'; import {ITelemetryService, ITelemetryAppender, ITelemetryInfo} from 'vs/platform/telemetry/common/telemetry'; +import {optional} from 'vs/platform/instantiation/common/instantiation'; +import {IConfigurationService} from 'vs/platform/configuration/common/configuration'; +import {IConfigurationRegistry, Extensions} from 'vs/platform/configuration/common/configurationRegistry'; import ErrorTelemetry from 'vs/platform/telemetry/common/errorTelemetry'; import {IdleMonitor, UserStatus} from 'vs/base/browser/idleMonitor'; import {TPromise} from 'vs/base/common/winjs.base'; import {IDisposable, dispose} from 'vs/base/common/lifecycle'; import {TimeKeeper, ITimerEvent} from 'vs/base/common/timer'; -import {withDefaults, cloneAndChange, mixin} from 'vs/base/common/objects'; +import {cloneAndChange, mixin} from 'vs/base/common/objects'; +import {Registry} from 'vs/platform/platform'; export interface ITelemetryServiceConfig { appender: ITelemetryAppender[]; - commonProperties?: TPromise<{ [name: string]: any }>[]; + commonProperties?: TPromise<{ [name: string]: any }>; piiPaths?: string[]; userOptIn?: boolean; enableHardIdle?: boolean; enableSoftIdle?: boolean; } -function createDefaultProperties(environment: IEnvironment): { [name: string]: any } { - - let seq = 0; - const startTime = Date.now(); - const sessionID = uuid.generateUuid() + Date.now(); - - let result = { - sessionID, - commitHash: environment.commitHash, - version: environment.version - }; - - // complex names and dynamic values - Object.defineProperties(result, { - 'timestamp': { - get: () => new Date(), - enumerable: true - }, - 'common.timesincesessionstart': { - get: () => Date.now() - startTime, - enumerable: true - }, - 'common.platform': { - get: () => Platform.Platform[Platform.platform], - enumerable: true - }, - 'common.sequence': { - get: () => seq++, - enumerable: true - } - }); - - return result; -} - export class TelemetryService implements ITelemetryService { // how long of inactivity before a user is considered 'inactive' - 2 minutes @@ -71,31 +38,25 @@ export class TelemetryService implements ITelemetryService { public serviceId = ITelemetryService; - protected _configuration: ITelemetryServiceConfig; - protected _disposables: IDisposable[] = []; - + private _configuration: ITelemetryServiceConfig; + private _disposables: IDisposable[] = []; private _timeKeeper: TimeKeeper; private _hardIdleMonitor: IdleMonitor; private _softIdleMonitor: IdleMonitor; - - private _commonProperties: TPromise<{ [name: string]: any }>; private _cleanupPatterns: [RegExp, string][] = []; constructor( config: ITelemetryServiceConfig, - @IWorkspaceContextService contextService: IWorkspaceContextService + @optional(IConfigurationService) private _configurationService: IConfigurationService ) { - this._configuration = withDefaults(config, { + this._configuration = mixin(config, { appender: [], - commonProperties: [], + commonProperties: TPromise.as({}), piiPaths: [], enableHardIdle: true, enableSoftIdle: true, userOptIn: true - }); - - this._commonProperties = TPromise.join(this._configuration.commonProperties) - .then(values => values.reduce((p, c) => mixin(p, c), createDefaultProperties(contextService.getConfiguration().env))); + }, false); // static cleanup patterns for: // #1 `file:///DANGEROUS/PATH/resources/app/Useful/Information` @@ -127,6 +88,17 @@ export class TelemetryService implements ITelemetryService { this._softIdleMonitor.addOneTimeIdleListener(() => this._onUserIdle()); this._disposables.push(this._softIdleMonitor); } + + if (this._configurationService) { + this._updateUserOptIn(); + this._configurationService.onDidUpdateConfiguration(this._updateUserOptIn, this, this._disposables); + this.publicLog('optInStatus', { optIn: this._configuration.userOptIn }); + } + } + + private _updateUserOptIn(): void { + const config = this._configurationService.getConfiguration(TELEMETRY_SECTION_ID); + this._configuration.userOptIn = config ? config.enableTelemetry : this._configuration.userOptIn; } private _onUserIdle(): void { @@ -153,7 +125,7 @@ export class TelemetryService implements ITelemetryService { } public getTelemetryInfo(): TPromise { - return this._commonProperties.then(values => { + return this._configuration.commonProperties.then(values => { // well known properties let sessionId = values['sessionID']; let instanceId = values['common.instanceId']; @@ -179,23 +151,20 @@ export class TelemetryService implements ITelemetryService { return event; } - public publicLog(eventName: string, data?: any): void { - this._handleEvent(eventName, data); - } + public publicLog(eventName: string, data?: any): TPromise { - private _handleEvent(eventName: string, data?: any): void { if (this._hardIdleMonitor && this._hardIdleMonitor.getStatus() === UserStatus.Idle) { - return; + return TPromise.as(undefined); } // don't send events when the user is optout unless the event is the opt{in|out} signal if (!this._configuration.userOptIn && eventName !== 'optInStatus') { - return; + return TPromise.as(undefined); } - // (first) add common properties - this._commonProperties.then(values => { + return this._configuration.commonProperties.then(values => { + // (first) add common properties data = mixin(data, values); // (last) remove all PII from data @@ -209,7 +178,8 @@ export class TelemetryService implements ITelemetryService { appender.log(eventName, data); } - }).done(undefined, err => { + }, err => { + // unsure what to do now... console.error(err); }); } @@ -226,3 +196,19 @@ export class TelemetryService implements ITelemetryService { } } + +const TELEMETRY_SECTION_ID = 'telemetry'; + +Registry.as(Extensions.Configuration).registerConfiguration({ + 'id': TELEMETRY_SECTION_ID, + 'order': 20, + 'type': 'object', + 'title': localize('telemetryConfigurationTitle', "Telemetry configuration"), + 'properties': { + 'telemetry.enableTelemetry': { + 'type': 'boolean', + 'description': localize('telemetry.enableTelemetry', "Enable usage data and errors to be sent to Microsoft."), + 'default': true + } + } +}); \ No newline at end of file diff --git a/src/vs/platform/telemetry/common/telemetry.ts b/src/vs/platform/telemetry/common/telemetry.ts index 1da414e865d..fb7cb081580 100644 --- a/src/vs/platform/telemetry/common/telemetry.ts +++ b/src/vs/platform/telemetry/common/telemetry.ts @@ -24,7 +24,7 @@ export interface ITelemetryService { * Sends a telemetry event that has been privacy approved. * Do not call this unless you have been given approval. */ - publicLog(eventName: string, data?: any): void; + publicLog(eventName: string, data?: any): any; /** * Starts a telemetry timer. Call stop() to send the event. diff --git a/src/vs/platform/telemetry/electron-browser/electronTelemetryService.ts b/src/vs/platform/telemetry/node/commonProperties.ts similarity index 65% rename from src/vs/platform/telemetry/electron-browser/electronTelemetryService.ts rename to src/vs/platform/telemetry/node/commonProperties.ts index 9345f9d225a..e4adcd89d29 100644 --- a/src/vs/platform/telemetry/electron-browser/electronTelemetryService.ts +++ b/src/vs/platform/telemetry/node/commonProperties.ts @@ -3,23 +3,17 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import getmac = require('getmac'); -import crypto = require('crypto'); -import winreg = require('winreg'); -import os = require('os'); -import { TPromise } from 'vs/base/common/winjs.base'; -import * as nls from 'vs/nls'; +import * as getmac from 'getmac'; +import * as crypto from 'crypto'; +import * as winreg from 'winreg'; +import * as Platform from 'vs/base/common/platform'; +import * as os from 'os'; +import {TPromise} from 'vs/base/common/winjs.base'; import * as errors from 'vs/base/common/errors'; import * as uuid from 'vs/base/common/uuid'; -import {TelemetryService, ITelemetryServiceConfig} from 'vs/platform/telemetry/browser/telemetryService'; -import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry'; import {IStorageService} from 'vs/platform/storage/common/storage'; import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace'; -import {IConfigurationService} from 'vs/platform/configuration/common/configuration'; -import {IConfigurationRegistry, Extensions} from 'vs/platform/configuration/common/configurationRegistry'; -import {Registry} from 'vs/platform/platform'; -const TELEMETRY_SECTION_ID = 'telemetry'; namespace StorageKeys { export const MachineId = 'telemetry.machineId'; @@ -31,10 +25,15 @@ namespace StorageKeys { export const SQM_KEY: string = '\\Software\\Microsoft\\SQMClient'; } -export function getDefaultProperties(storageService: IStorageService): TPromise<{ [name: string]: string }> { +export function resolveCommonProperties(storageService: IStorageService, contextService: IWorkspaceContextService): TPromise<{ [name: string]: string }> { + let result: { [name: string]: any } = Object.create(null); + result['sessionID'] = uuid.generateUuid() + Date.now(); + result['commitHash'] = contextService.getConfiguration().env.commitHash; + // add shell & render version + result['version'] = contextService.getConfiguration().env.version; result['common.version.shell'] = process.versions && (process).versions['electron']; result['common.version.renderer'] = process.versions && (process).versions['chrome']; result['common.osVersion'] = os.release(); @@ -48,15 +47,39 @@ export function getDefaultProperties(storageService: IStorageService): TPromise< result['common.lastSessionDate'] = lastSessionDate; result['common.isNewSession'] = !lastSessionDate ? 1 : 0; + + // dynamic properties which value differs on each call + let seq = 0; + const startTime = Date.now(); + Object.defineProperties(result, { + 'timestamp': { + get: () => new Date(), + enumerable: true + }, + 'common.timesincesessionstart': { + get: () => Date.now() - startTime, + enumerable: true + }, + 'common.platform': { + get: () => Platform.Platform[Platform.platform], + enumerable: true + }, + 'common.sequence': { + get: () => seq++, + enumerable: true + } + }); + // promise based properties - result['common.instanceId'] = getOrCreateInstanceId(storageService); - result['common.machineId'] = getOrCreateMachineId(storageService); + let promises: TPromise[] = []; + promises.push(getOrCreateInstanceId(storageService).then(value => result['common.instanceId'] = value)); + promises.push(getOrCreateMachineId(storageService).then(value => result['common.machineId'] = value)); if (process.platform === 'win32') { - result['common.sqm.userid'] = getSqmUserId(storageService); - result['common.sqm.machineid'] = getSqmMachineId(storageService); + promises.push(getSqmUserId(storageService).then(value => result['common.sqm.userid']= value)); + promises.push(getSqmMachineId(storageService).then(value => result['common.sqm.machineid']= value)); } - return TPromise.join(result); + return TPromise.join(promises).then(_ => result); } function getOrCreateInstanceId( storageService: IStorageService): TPromise { @@ -142,37 +165,3 @@ function getWinRegKeyData(key: string, name: string, hive: string): TPromise(TELEMETRY_SECTION_ID); - this._configuration.userOptIn = config ? config.enableTelemetry : this._configuration.userOptIn; - } -} - -Registry.as(Extensions.Configuration).registerConfiguration({ - 'id': TELEMETRY_SECTION_ID, - 'order': 20, - 'type': 'object', - 'title': nls.localize('telemetryConfigurationTitle', "Telemetry configuration"), - 'properties': { - 'telemetry.enableTelemetry': { - 'type': 'boolean', - 'description': nls.localize('telemetry.enableTelemetry', "Enable usage data and errors to be sent to Microsoft."), - 'default': true - } - } -}); \ No newline at end of file diff --git a/src/vs/platform/telemetry/test/node/commonProperties.test.ts b/src/vs/platform/telemetry/test/node/commonProperties.test.ts new file mode 100644 index 00000000000..7fccae2ff8a --- /dev/null +++ b/src/vs/platform/telemetry/test/node/commonProperties.test.ts @@ -0,0 +1,76 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +import * as assert from 'assert'; +import {TPromise} from 'vs/base/common/winjs.base'; +import {resolveCommonProperties} from 'vs/platform/telemetry/node/commonProperties'; +import {TestStorageService, TestContextService} from 'vs/workbench/test/browser/servicesTestUtils'; + +suite('Telemetry - common properties', function () { + + test('default', function () { + + return resolveCommonProperties(new TestStorageService(), new TestContextService()).then(props => { + + assert.equal(Object.keys(props).length, 15); + + assert.ok('commitHash' in props); + assert.ok('sessionID' in props); + assert.ok('timestamp' in props); + assert.ok('common.platform' in props); + assert.ok('common.timesincesessionstart' in props); + assert.ok('common.sequence' in props); + + // assert.ok('common.version.shell' in first.data); // only when running on electron + // assert.ok('common.version.renderer' in first.data); + assert.ok('common.osVersion' in props, 'osVersion'); + assert.ok('version' in props); + + assert.ok('common.firstSessionDate' in props, 'firstSessionDate'); + assert.ok('common.lastSessionDate' in props, 'lastSessionDate'); // conditional, see below, 'lastSessionDate'ow + assert.ok('common.isNewSession' in props, 'isNewSession'); + + // machine id et al + assert.ok('common.instanceId' in props, 'instanceId'); + assert.ok('common.machineId' in props, 'machineId'); + if (process.platform === 'win32') { // SQM only on windows + assert.ok('common.sqm.userid' in props, 'userid'); + assert.ok('common.sqm.machineid' in props, 'machineid'); + } + }); + }); + + test('lastSessionDate when aviablale', function () { + + let service = new TestStorageService(); + service.store('telemetry.lastSessionDate', new Date().toUTCString()); + + return resolveCommonProperties(service, new TestContextService()).then(props => { + + assert.ok('common.lastSessionDate' in props); // conditional, see below + assert.ok('common.isNewSession' in props); + assert.equal(props['common.isNewSession'], 0); + }); + }); + + test('values chance on ask', function () { + return resolveCommonProperties(new TestStorageService(), new TestContextService()).then(props => { + let value1 = props['common.sequence']; + let value2 = props['common.sequence']; + assert.ok(value1 !== value2, 'seq'); + + value1 = props['timestamp']; + value2 = props['timestamp']; + assert.ok(value1 !== value2, 'timestamp'); + + value1 = props['common.timesincesessionstart']; + return TPromise.timeout(10).then(_ => { + value2 = props['common.timesincesessionstart']; + assert.ok(value1 !== value2, 'timesincesessionstart'); + }); + }); + }); +}); diff --git a/src/vs/platform/telemetry/test/node/defaultProperties.test.ts b/src/vs/platform/telemetry/test/node/defaultProperties.test.ts deleted file mode 100644 index 953ba6f11e4..00000000000 --- a/src/vs/platform/telemetry/test/node/defaultProperties.test.ts +++ /dev/null @@ -1,47 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -'use strict'; - -import * as assert from 'assert'; -import {getDefaultProperties} from 'vs/platform/telemetry/electron-browser/electronTelemetryService'; -import {TestStorageService} from 'vs/workbench/test/browser/servicesTestUtils'; - -suite('Telemetry - common properties', function () { - - test('getDefaultProperties', function () { - - return getDefaultProperties(new TestStorageService()).then(props => { - - // assert.ok('common.version.shell' in first.data); // only when running on electron - // assert.ok('common.version.renderer' in first.data); - assert.ok('common.osVersion' in props, 'osVersion'); - - assert.ok('common.firstSessionDate' in props, 'firstSessionDate'); - assert.ok(!('common.lastSessionDate' in props), 'lastSessionDate'); // conditional, see bel, 'lastSessionDate'ow - assert.ok('common.isNewSession' in props, 'isNewSession'); - - // machine id et al - assert.ok('common.instanceId' in props, 'instanceId'); - assert.ok('common.machineId' in props, 'machineId'); - if (process.platform === 'win32') { // SQM only on windows - assert.ok('common.sqm.userid' in props, 'userid'); - assert.ok('common.sqm.machineid' in props, 'machineid'); - } - }); - }); - - test('getDefaultProperties, lastSessionDate when aviablale', function () { - - let service = new TestStorageService(); - service.store('telemetry.lastSessionDate', new Date().toUTCString()); - - return getDefaultProperties(service).then(props => { - - assert.ok('common.lastSessionDate' in props); // conditional, see below - assert.ok('common.isNewSession' in props); - assert.equal(props['common.isNewSession'], 0); - }); - }); -}); diff --git a/src/vs/platform/telemetry/test/node/telemetryService.test.ts b/src/vs/platform/telemetry/test/node/telemetryService.test.ts index 09f5e465079..a78b2b43f6d 100644 --- a/src/vs/platform/telemetry/test/node/telemetryService.test.ts +++ b/src/vs/platform/telemetry/test/node/telemetryService.test.ts @@ -6,9 +6,10 @@ import * as assert from 'assert'; import IdleMonitor = require('vs/base/browser/idleMonitor'); +import {Emitter} from 'vs/base/common/event'; +import {TPromise} from 'vs/base/common/winjs.base'; import {TelemetryService} from 'vs/platform/telemetry/browser/telemetryService'; import Telemetry = require('vs/platform/telemetry/common/telemetry'); -import {TestContextService} from 'vs/workbench/test/browser/servicesTestUtils'; import Errors = require('vs/base/common/errors'); import Timer = require('vs/base/common/timer'); import * as sinon from 'sinon'; @@ -82,101 +83,47 @@ class ErrorTestingSettings { suite('TelemetryService', () => { - class AppenderCountTelemetryService extends TelemetryService { - getAppendersCount() { - return this._configuration.appender.length; - } - } - - // Appenders - test('No appenders', sinon.test(function() { - let service = new AppenderCountTelemetryService(undefined, new TestContextService()); - assert.equal(service.getAppendersCount(), 0); - - // log events - service.publicLog('testEvent'); - let timedEvent = service.timedPublicLog('testTimed', { 'somedata': 'test' }); - timedEvent.stop(); - - //dispose - service.dispose(); - })); - - test('Disposing', sinon.test(function() { + test('Disposing', sinon.test(function () { let testAppender = new TestTelemetryAppender(); - let service = new TelemetryService({ appender: [testAppender] }, new TestContextService()); + let service = new TelemetryService({ appender: [testAppender] }, undefined); - service.publicLog('testPrivateEvent'); - assert.equal(testAppender.getEventsCount(), 1); + return service.publicLog('testPrivateEvent').then(() => { + assert.equal(testAppender.getEventsCount(), 1); - service.dispose(); - assert.equal(testAppender.isDisposed, true); + service.dispose(); + assert.equal(testAppender.isDisposed, true); + }); })); // event reporting - test('Simple event', sinon.test(function() { + test('Simple event', sinon.test(function () { let testAppender = new TestTelemetryAppender(); - let service = new TelemetryService({ appender: [testAppender] }, new TestContextService()); + let service = new TelemetryService({ appender: [testAppender] }, undefined); - return service.getTelemetryInfo().then(info => { - - - service.publicLog('testEvent'); + return service.publicLog('testEvent').then(_ => { assert.equal(testAppender.getEventsCount(), 1); assert.equal(testAppender.events[0].eventName, 'testEvent'); assert.notEqual(testAppender.events[0].data, null); - assert.equal(testAppender.events[0].data['sessionID'], info.sessionId); - assert.notEqual(testAppender.events[0].data['timestamp'], null); service.dispose(); }); })); - test('default properties', function () { + test('Event with data', sinon.test(function () { let testAppender = new TestTelemetryAppender(); - let service = new TelemetryService({ appender: [testAppender] }, new TestContextService()); + let service = new TelemetryService({ appender: [testAppender] }, undefined); - return service.getTelemetryInfo().then(info => { - - service.publicLog('testEvent'); - let [first] = testAppender.events; - - assert.equal(Object.keys(first.data).length, 7); - assert.ok('version' in first.data); - assert.ok('commitHash' in first.data); - assert.ok('sessionID' in first.data); - assert.ok('timestamp' in first.data); - assert.ok('common.platform' in first.data); - assert.ok('common.timesincesessionstart' in first.data); - assert.ok('common.sequence' in first.data); - - // assert.equal(Object.keys(first.data).length, 9); - // assert.ok('common.instanceId' in first.data); - // assert.ok('common.machineId' in first.data); - - service.dispose(); - }); - }); - - test('Event with data', sinon.test(function() { - let testAppender = new TestTelemetryAppender(); - let service = new TelemetryService({ appender: [testAppender] }, new TestContextService()); - - return service.getTelemetryInfo().then(info => { - - service.publicLog('testEvent', { - 'stringProp': 'property', - 'numberProp': 1, - 'booleanProp': true, - 'complexProp': { - 'value': 0 - } - }); + return service.publicLog('testEvent', { + 'stringProp': 'property', + 'numberProp': 1, + 'booleanProp': true, + 'complexProp': { + 'value': 0 + } + }).then(() => { assert.equal(testAppender.getEventsCount(), 1); assert.equal(testAppender.events[0].eventName, 'testEvent'); assert.notEqual(testAppender.events[0].data, null); - assert.equal(testAppender.events[0].data['sessionID'], info.sessionId); - assert.notEqual(testAppender.events[0].data['timestamp'], null); assert.equal(testAppender.events[0].data['stringProp'], 'property'); assert.equal(testAppender.events[0].data['numberProp'], 1); assert.equal(testAppender.events[0].data['booleanProp'], true); @@ -187,11 +134,66 @@ suite('TelemetryService', () => { })); - test('Telemetry Timer events', sinon.test(function() { + test('common properties added to *all* events, simple event', function () { + let testAppender = new TestTelemetryAppender(); + let service = new TelemetryService({ + appender: [testAppender], + commonProperties: TPromise.as({ foo: 'JA!', get bar() { return Math.random(); } }) + }, undefined); + + return service.publicLog('testEvent').then(_ => { + let [first] = testAppender.events; + + assert.equal(Object.keys(first.data).length, 2); + assert.equal(typeof first.data['foo'], 'string'); + assert.equal(typeof first.data['bar'], 'number'); + + service.dispose(); + }); + }); + + test('common properties added to *all* events, event with data', function () { + let testAppender = new TestTelemetryAppender(); + let service = new TelemetryService({ + appender: [testAppender], + commonProperties: TPromise.as({ foo: 'JA!', get bar() { return Math.random(); } }) + }, undefined); + + return service.publicLog('testEvent', { hightower: 'xl', price: 8000 }).then(_ => { + let [first] = testAppender.events; + + assert.equal(Object.keys(first.data).length, 4); + assert.equal(typeof first.data['foo'], 'string'); + assert.equal(typeof first.data['bar'], 'number'); + assert.equal(typeof first.data['hightower'], 'string'); + assert.equal(typeof first.data['price'], 'number'); + + service.dispose(); + }); + }); + + test('TelemetryInfo comes from properties', function () { + let service = new TelemetryService({ + appender: [], + commonProperties: TPromise.as({ + sessionID: 'one', + ['common.instanceId']: 'two', + ['common.machineId']: 'three', + }) + }, undefined); + + return service.getTelemetryInfo().then(info => { + assert.equal(info.sessionId, 'one'); + assert.equal(info.instanceId, 'two'); + assert.equal(info.machineId, 'three'); + }); + }); + + test('Telemetry Timer events', sinon.test(function () { Timer.ENABLE_TIMER = true; let testAppender = new TestTelemetryAppender(); - let service = new TelemetryService({ appender: [testAppender] }, new TestContextService()); + let service = new TelemetryService({ appender: [testAppender] }, undefined); let t1 = service.timedPublicLog('editorDance'); this.clock.tick(20); @@ -221,25 +223,26 @@ suite('TelemetryService', () => { Timer.ENABLE_TIMER = false; })); - test('enableTelemetry on by default', sinon.test(function() { + test('enableTelemetry on by default', sinon.test(function () { let testAppender = new TestTelemetryAppender(); - let service = new TelemetryService({ appender: [testAppender] }, new TestContextService()); + let service = new TelemetryService({ appender: [testAppender] }, undefined); - service.publicLog('testEvent'); - assert.equal(testAppender.getEventsCount(), 1); - assert.equal(testAppender.events[0].eventName, 'testEvent'); + return service.publicLog('testEvent').then(() => { + assert.equal(testAppender.getEventsCount(), 1); + assert.equal(testAppender.events[0].eventName, 'testEvent'); - service.dispose(); + service.dispose(); + }); })); - test('Error events', sinon.test(function() { + test('Error events', sinon.test(function () { let origErrorHandler = Errors.errorHandler.getUnexpectedErrorHandler(); Errors.setUnexpectedErrorHandler(() => { }); try { let testAppender = new TestTelemetryAppender(); - let service = new TelemetryService({ appender: [testAppender] }, new TestContextService()); + let service = new TelemetryService({ appender: [testAppender] }, undefined); let e: any = new Error('This is a test.'); @@ -289,11 +292,11 @@ suite('TelemetryService', () => { // } // })); - test('Handle global errors', sinon.test(function() { + test('Handle global errors', sinon.test(function () { let errorStub = this.stub(window, 'onerror'); let testAppender = new TestTelemetryAppender(); - let service = new TelemetryService({ appender: [testAppender] }, new TestContextService()); + let service = new TelemetryService({ appender: [testAppender] }, undefined); let testError = new Error('test'); (window.onerror)('Error Message', 'file.js', 2, 42, testError); @@ -313,11 +316,11 @@ suite('TelemetryService', () => { service.dispose(); })); - test('Uncaught Error Telemetry removes PII from filename', sinon.test(function() { + test('Uncaught Error Telemetry removes PII from filename', sinon.test(function () { let errorStub = this.stub(window, 'onerror'); let settings = new ErrorTestingSettings(); let testAppender = new TestTelemetryAppender(); - let service = new TelemetryService({ appender: [testAppender] }, new TestContextService()); + let service = new TelemetryService({ appender: [testAppender] }, undefined); let dangerousFilenameError: any = new Error('dangerousFilename'); dangerousFilenameError.stack = settings.stack; @@ -339,13 +342,13 @@ suite('TelemetryService', () => { service.dispose(); })); - test('Unexpected Error Telemetry removes PII', sinon.test(function() { + test('Unexpected Error Telemetry removes PII', sinon.test(function () { let origErrorHandler = Errors.errorHandler.getUnexpectedErrorHandler(); Errors.setUnexpectedErrorHandler(() => { }); try { let settings = new ErrorTestingSettings(); let testAppender = new TestTelemetryAppender(); - let service = new TelemetryService({ appender: [testAppender] }, new TestContextService()); + let service = new TelemetryService({ appender: [testAppender] }, undefined); let dangerousPathWithoutImportantInfoError: any = new Error(settings.dangerousPathWithoutImportantInfo); dangerousPathWithoutImportantInfoError.stack = settings.stack; @@ -367,11 +370,11 @@ suite('TelemetryService', () => { } })); - test('Uncaught Error Telemetry removes PII', sinon.test(function() { + test('Uncaught Error Telemetry removes PII', sinon.test(function () { let errorStub = this.stub(window, 'onerror'); let settings = new ErrorTestingSettings(); let testAppender = new TestTelemetryAppender(); - let service = new TelemetryService({ appender: [testAppender] }, new TestContextService()); + let service = new TelemetryService({ appender: [testAppender] }, undefined); let dangerousPathWithoutImportantInfoError: any = new Error('dangerousPathWithoutImportantInfo'); dangerousPathWithoutImportantInfoError.stack = settings.stack; @@ -390,7 +393,7 @@ suite('TelemetryService', () => { service.dispose(); })); - test('Unexpected Error Telemetry removes PII but preserves Code file path', sinon.test(function() { + test('Unexpected Error Telemetry removes PII but preserves Code file path', sinon.test(function () { let origErrorHandler = Errors.errorHandler.getUnexpectedErrorHandler(); Errors.setUnexpectedErrorHandler(() => { }); @@ -398,7 +401,7 @@ suite('TelemetryService', () => { try { let settings = new ErrorTestingSettings(); let testAppender = new TestTelemetryAppender(); - let service = new TelemetryService({ appender: [testAppender] }, new TestContextService()); + let service = new TelemetryService({ appender: [testAppender] }, undefined); let dangerousPathWithImportantInfoError: any = new Error(settings.dangerousPathWithImportantInfo); dangerousPathWithImportantInfoError.stack = settings.stack; @@ -423,11 +426,11 @@ suite('TelemetryService', () => { } })); - test('Uncaught Error Telemetry removes PII but preserves Code file path', sinon.test(function() { + test('Uncaught Error Telemetry removes PII but preserves Code file path', sinon.test(function () { let errorStub = this.stub(window, 'onerror'); let settings = new ErrorTestingSettings(); let testAppender = new TestTelemetryAppender(); - let service = new TelemetryService({ appender: [testAppender] }, new TestContextService()); + let service = new TelemetryService({ appender: [testAppender] }, undefined); let dangerousPathWithImportantInfoError: any = new Error('dangerousPathWithImportantInfo'); dangerousPathWithImportantInfoError.stack = settings.stack; @@ -448,7 +451,7 @@ suite('TelemetryService', () => { service.dispose(); })); - test('Unexpected Error Telemetry removes PII but preserves Missing Model error message', sinon.test(function() { + test('Unexpected Error Telemetry removes PII but preserves Missing Model error message', sinon.test(function () { let origErrorHandler = Errors.errorHandler.getUnexpectedErrorHandler(); Errors.setUnexpectedErrorHandler(() => { }); @@ -456,7 +459,7 @@ suite('TelemetryService', () => { try { let settings = new ErrorTestingSettings(); let testAppender = new TestTelemetryAppender(); - let service = new TelemetryService({ appender: [testAppender] }, new TestContextService()); + let service = new TelemetryService({ appender: [testAppender] }, undefined); let missingModelError: any = new Error(settings.missingModelMessage); missingModelError.stack = settings.stack; @@ -481,11 +484,11 @@ suite('TelemetryService', () => { } })); - test('Uncaught Error Telemetry removes PII but preserves Missing Model error message', sinon.test(function() { + test('Uncaught Error Telemetry removes PII but preserves Missing Model error message', sinon.test(function () { let errorStub = this.stub(window, 'onerror'); let settings = new ErrorTestingSettings(); let testAppender = new TestTelemetryAppender(); - let service = new TelemetryService({ appender: [testAppender] }, new TestContextService()); + let service = new TelemetryService({ appender: [testAppender] }, undefined); let missingModelError: any = new Error('missingModelMessage'); missingModelError.stack = settings.stack; @@ -507,7 +510,7 @@ suite('TelemetryService', () => { service.dispose(); })); - test('Unexpected Error Telemetry removes PII but preserves No Such File error message', sinon.test(function() { + test('Unexpected Error Telemetry removes PII but preserves No Such File error message', sinon.test(function () { let origErrorHandler = Errors.errorHandler.getUnexpectedErrorHandler(); Errors.setUnexpectedErrorHandler(() => { }); @@ -515,7 +518,7 @@ suite('TelemetryService', () => { try { let settings = new ErrorTestingSettings(); let testAppender = new TestTelemetryAppender(); - let service = new TelemetryService({ appender: [testAppender] }, new TestContextService()); + let service = new TelemetryService({ appender: [testAppender] }, undefined); let noSuchFileError: any = new Error(settings.noSuchFileMessage); noSuchFileError.stack = settings.stack; @@ -540,7 +543,7 @@ suite('TelemetryService', () => { } })); - test('Uncaught Error Telemetry removes PII but preserves No Such File error message', sinon.test(function() { + test('Uncaught Error Telemetry removes PII but preserves No Such File error message', sinon.test(function () { let origErrorHandler = Errors.errorHandler.getUnexpectedErrorHandler(); Errors.setUnexpectedErrorHandler(() => { }); @@ -548,7 +551,7 @@ suite('TelemetryService', () => { let errorStub = this.stub(window, 'onerror'); let settings = new ErrorTestingSettings(); let testAppender = new TestTelemetryAppender(); - let service = new TelemetryService({ appender: [testAppender] }, new TestContextService()); + let service = new TelemetryService({ appender: [testAppender] }, undefined); let noSuchFileError: any = new Error('noSuchFileMessage'); noSuchFileError.stack = settings.stack; @@ -574,10 +577,10 @@ suite('TelemetryService', () => { } })); - test('Test hard idle does not affect sending normal events in active state', sinon.test(function() { + test('Test hard idle does not affect sending normal events in active state', sinon.test(function () { let testAppender = new TestTelemetryAppender(); - let service = new TelemetryService({ enableHardIdle: true, enableSoftIdle: false, appender: [testAppender] }, new TestContextService()); + let service = new TelemetryService({ enableHardIdle: true, enableSoftIdle: false, appender: [testAppender] }, undefined); //report an event @@ -590,24 +593,25 @@ suite('TelemetryService', () => { })); - test('Test hard idle stops events from being sent in idle state', sinon.test(function() { + test('Test hard idle stops events from being sent in idle state', sinon.test(function () { let testAppender = new TestTelemetryAppender(); - let service = new TelemetryService({ enableHardIdle: true, enableSoftIdle: false, appender: [testAppender] }, new TestContextService()); + let service = new TelemetryService({ enableHardIdle: true, enableSoftIdle: false, appender: [testAppender] }, undefined); // make the user idle this.clock.tick(IdleMonitor.DEFAULT_IDLE_TIME); //report an event - service.publicLog('testEvent'); + return service.publicLog('testEvent').then(() => { + //verify that the event is not being sent + assert.equal(testAppender.getEventsCount(), 0); - //verify that the event is not being sent - assert.equal(testAppender.getEventsCount(), 0); + service.dispose(); + }); - service.dispose(); })); - test('Test soft idle start/stop events', sinon.test(function() { + test('Test soft idle start/stop events', sinon.test(function () { let activeListener: () => void = null; let idleListener: () => void = null; @@ -616,22 +620,22 @@ suite('TelemetryService', () => { assert.equal(timeout, TelemetryService.SOFT_IDLE_TIME); } - MockIdleMonitor.prototype.addOneTimeActiveListener = function(callback: () => void): void { + MockIdleMonitor.prototype.addOneTimeActiveListener = function (callback: () => void): void { activeListener = callback; }; - MockIdleMonitor.prototype.addOneTimeIdleListener = function(callback: () => void): void { + MockIdleMonitor.prototype.addOneTimeIdleListener = function (callback: () => void): void { idleListener = callback; }; - MockIdleMonitor.prototype.dispose = function() { + MockIdleMonitor.prototype.dispose = function () { // empty }; this.stub(IdleMonitor, 'IdleMonitor', MockIdleMonitor); let testAppender = new TestTelemetryAppender(); - let service = new TelemetryService({ enableHardIdle: false, enableSoftIdle: true, appender: [testAppender] }, new TestContextService()); + let service = new TelemetryService({ enableHardIdle: false, enableSoftIdle: true, appender: [testAppender] }, undefined); assert.equal(testAppender.getEventsCount(), 0); @@ -653,37 +657,73 @@ suite('TelemetryService', () => { service.dispose(); })); - test('Telemetry Service respects user opt-in settings', sinon.test(function() { + test('Telemetry Service respects user opt-in settings', sinon.test(function () { let testAppender = new TestTelemetryAppender(); - let service = new TelemetryService({userOptIn: false, appender: [testAppender] }, new TestContextService()); + let service = new TelemetryService({ userOptIn: false, appender: [testAppender] }, undefined); - service.publicLog('testEvent'); - assert.equal(testAppender.getEventsCount(), 0); - - service.dispose(); + return service.publicLog('testEvent').then(() => { + assert.equal(testAppender.getEventsCount(), 0); + service.dispose(); + }); })); - test('Telemetry Service sends events when enableTelemetry is on even user optin is on', sinon.test(function() { + test('Telemetry Service sends events when enableTelemetry is on even user optin is on', sinon.test(function () { let testAppender = new TestTelemetryAppender(); - let service = new TelemetryService({userOptIn: true, appender: [testAppender] }, new TestContextService()); + let service = new TelemetryService({ userOptIn: true, appender: [testAppender] }, undefined); - service.publicLog('testEvent'); - assert.equal(testAppender.getEventsCount(), 1); - - service.dispose(); + return service.publicLog('testEvent').then(() => { + assert.equal(testAppender.getEventsCount(), 1); + service.dispose(); + }); })); - test('Telemetry Service allows optin friendly events', sinon.test(function() { + test('Telemetry Service allows optin friendly events', sinon.test(function () { let testAppender = new TestTelemetryAppender(); - let service = new TelemetryService({userOptIn: false, appender: [testAppender] }, new TestContextService()); + let service = new TelemetryService({ userOptIn: false, appender: [testAppender] }, undefined); - service.publicLog('testEvent'); - assert.equal(testAppender.getEventsCount(), 0); - - service.publicLog(optInStatusEventName, {userOptIn: false}); - assert.equal(testAppender.getEventsCount(), 1); - assert.equal(testAppender.events[0].eventName, optInStatusEventName); - assert.equal(testAppender.events[0].data.userOptIn, false); - service.dispose(); + return service.publicLog('testEvent').then(() => { + assert.equal(testAppender.getEventsCount(), 0); + return service.publicLog(optInStatusEventName, { userOptIn: false }); + }).then(() => { + assert.equal(testAppender.getEventsCount(), 1); + assert.equal(testAppender.events[0].eventName, optInStatusEventName); + assert.equal(testAppender.events[0].data.userOptIn, false); + service.dispose(); + }); })); + + test('Telemetry Service checks with config service', function () { + + let enableTelemetry = false; + let emitter = new Emitter(); + + let testAppender = new TestTelemetryAppender(); + let service = new TelemetryService({ + appender: [testAppender] + }, { + serviceId: undefined, + hasWorkspaceConfiguration() { + return false; + }, + getConfiguration() { + return { + enableTelemetry + }; + }, + loadConfiguration() { + return TPromise.as(this.getConfiguration()); + }, + onDidUpdateConfiguration: emitter.event + }); + + assert.equal(service.isOptedIn, false); + + enableTelemetry = true; + emitter.fire({}); + assert.equal(service.isOptedIn, true); + + enableTelemetry = false; + emitter.fire({}); + assert.equal(service.isOptedIn, false); + }); }); \ No newline at end of file diff --git a/src/vs/workbench/electron-browser/shell.ts b/src/vs/workbench/electron-browser/shell.ts index 907f822252d..ca2802b3c91 100644 --- a/src/vs/workbench/electron-browser/shell.ts +++ b/src/vs/workbench/electron-browser/shell.ts @@ -20,8 +20,9 @@ import timer = require('vs/base/common/timer'); import {Workbench} from 'vs/workbench/browser/workbench'; import {Storage, inMemoryLocalStorageInstance} from 'vs/workbench/common/storage'; import {ITelemetryService, NullTelemetryService} from 'vs/platform/telemetry/common/telemetry'; -import {ElectronTelemetryService, getDefaultProperties} from 'vs/platform/telemetry/electron-browser/electronTelemetryService'; +import {TelemetryService} from 'vs/platform/telemetry/browser/telemetryService'; import {AppInsightsAppender} from 'vs/platform/telemetry/node/appInsightsAppender'; +import {resolveCommonProperties} from 'vs/platform/telemetry/node/commonProperties'; import {ElectronIntegration} from 'vs/workbench/electron-browser/integration'; import {Update} from 'vs/workbench/electron-browser/update'; import {WorkspaceStats} from 'vs/platform/telemetry/common/workspaceStats'; @@ -204,11 +205,11 @@ export class WorkbenchShell { this.storageService = new Storage(this.contextService, window.localStorage, disableWorkspaceStorage ? inMemoryLocalStorageInstance : window.localStorage); if (this.configuration.env.isBuilt && !this.configuration.env.extensionDevelopmentPath && !!this.configuration.env.enableTelemetry) { - this.telemetryService = new ElectronTelemetryService({ + this.telemetryService = new TelemetryService({ appender: [new AppInsightsAppender(this.configuration.env.aiConfig)], - commonProperties: [getDefaultProperties(this.storageService)], + commonProperties: resolveCommonProperties(this.storageService, this.contextService), piiPaths: [this.configuration.env.appRoot, this.configuration.env.userExtensionsHome] - }, this.configurationService, this.contextService); + }, this.configurationService); } else { this.telemetryService = NullTelemetryService; } From 92d4db4f6c396e8c701413a7fc0cda8e3893f9b8 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Tue, 10 May 2016 12:06:46 +0200 Subject: [PATCH 119/297] [php] Switch to textmate grammar. Fixes #5986 --- extensions/php/package.json | 7 +- extensions/php/php.configuration.json | 1 + extensions/php/syntaxes/php.json | 2638 +++++++++++++++++ .../php/test/colorize-results/test_php.json | 2118 ++++++++----- src/vs/editor/editor.main.ts | 1 + src/vs/languages/languages.main.ts | 1 - 6 files changed, 4002 insertions(+), 764 deletions(-) create mode 100644 extensions/php/syntaxes/php.json diff --git a/extensions/php/package.json b/extensions/php/package.json index 6f235863bbc..138adcf85fc 100644 --- a/extensions/php/package.json +++ b/extensions/php/package.json @@ -11,11 +11,16 @@ "contributes": { "languages": [{ "id": "php", - "extensions": [ ".php", ".phtml", ".ctp" ], + "extensions": [ ".php", ".php4", ".php5", ".phtml", ".ctp" ], "aliases": [ "PHP", "php" ], "mimetypes": ["application/x-php"], "configuration": "./php.configuration.json" }], + "grammars": [{ + "language": "php", + "scopeName": "text.html.php", + "path": "./syntaxes/php.json" + }], "snippets": [{ "language": "php", "path": "./snippets/php.json" diff --git a/extensions/php/php.configuration.json b/extensions/php/php.configuration.json index c23d14262e4..431ee4bc667 100644 --- a/extensions/php/php.configuration.json +++ b/extensions/php/php.configuration.json @@ -8,4 +8,5 @@ ["[", "]"], ["(", ")"] ] + } \ No newline at end of file diff --git a/extensions/php/syntaxes/php.json b/extensions/php/syntaxes/php.json new file mode 100644 index 00000000000..d42cb29a19d --- /dev/null +++ b/extensions/php/syntaxes/php.json @@ -0,0 +1,2638 @@ +{ + "scopeName": "text.html.php", + "name": "PHP", + "fileTypes": [ + "aw", + "ctp", + "inc", + "install", + "module", + "php", + "php_cs", + "php3", + "php4", + "php5", + "phpt", + "phtml", + "profile" + ], + "firstLineMatch": "^#!.*(?))", + "beginCaptures": { + "0": { + "name": "punctuation.whitespace.embedded.leading.php" + } + }, + "end": "(?!\\G)(\\s*$\\n)?", + "endCaptures": { + "0": { + "name": "punctuation.whitespace.embedded.trailing.php" + } + }, + "patterns": [ + { + "begin": "<\\?(?i:php|=)?", + "beginCaptures": { + "0": { + "name": "punctuation.section.embedded.metatag.begin.php" + } + }, + "contentName": "source.php", + "end": "(\\?)>", + "endCaptures": { + "0": { + "name": "punctuation.section.embedded.metatag.end.php" + }, + "1": { + "name": "source.php" + } + }, + "name": "meta.embedded.block.php", + "patterns": [ + { + "include": "#language" + } + ] + } + ] + }, + { + "begin": "<\\?(?i:php|=)?(?![^?]*\\?>)", + "beginCaptures": { + "0": { + "name": "punctuation.section.embedded.begin.php" + } + }, + "contentName": "source.php", + "end": "(\\?)>", + "endCaptures": { + "0": { + "name": "punctuation.section.embedded.end.php" + }, + "1": { + "name": "source.php" + } + }, + "name": "meta.embedded.block.php", + "patterns": [ + { + "include": "#language" + } + ] + }, + { + "begin": "<\\?(?i:php|=)?", + "beginCaptures": { + "0": { + "name": "punctuation.section.embedded.begin.php" + } + }, + "end": ">", + "endCaptures": { + "0": { + "name": "punctuation.section.embedded.end.php" + } + }, + "name": "meta.embedded.line.php", + "patterns": [ + { + "captures": { + "1": { + "name": "source.php" + }, + "2": { + "name": "punctuation.section.embedded.end.php" + }, + "3": { + "name": "source.php" + } + }, + "match": "\\G(\\s*)((\\?))(?=>)", + "name": "meta.special.empty-tag.php" + }, + { + "begin": "\\G", + "contentName": "source.php", + "end": "(\\?)(?=>)", + "endCaptures": { + "0": { + "name": "punctuation.section.embedded.end.php" + }, + "1": { + "name": "source.php" + } + }, + "patterns": [ + { + "include": "#language" + } + ] + } + ] + } + ] + } + }, + "patterns": [ + { + "include": "text.html.basic" + } + ], + "repository": { + "class-builtin": { + "patterns": [ + { + "captures": { + "1": { + "name": "punctuation.separator.inheritance.php" + } + }, + "match": "(?i)(\\\\)?\\b(st(dClass|reamWrapper)|R(RD(Graph|Creator|Updater)|untimeException|e(sourceBundle|cursive(RegexIterator|Ca(chingIterator|llbackFilterIterator)|TreeIterator|Iterator(Iterator)?|DirectoryIterator|FilterIterator|ArrayIterator)|flect(ion(Method|Class|ZendExtension|Object|P(arameter|roperty)|Extension|Function(Abstract)?)?|or)|gexIterator)|angeException)|G(ender\\Gender|lobIterator|magick(Draw|Pixel)?)|X(sltProcessor|ML(Reader|Diff\\\\(Memory|Base|DOM|File)|Writer)|SLTProcessor)|M(ysqlndUh(Connection|PreparedStatement)|ongo(Re(sultException|gex)|Grid(fsFile|FS(Cursor|File)?)|BinData|C(o(de|llection|mmandCursor)|ursor(Exception)?|lient)|Timestamp|I(n(sertBatch|t(32|64))|d)|D(B(Ref)?|eleteBatch|ate)|UpdateBatch|Pool|Write(Batch|ConcernException)|Log)?|u(tex|ltipleIterator)|e(ssageFormatter|mcache(d)?))|Bad(MethodCallException|FunctionCallException)|tidy(Node)?|S(ync(ReaderWriter|Mutex|Semaphore|Event)|impleXML(Iterator|Element)|oap(Server|Header|Client|Param|Var|Fault)|NMP|CA(_(SoapProxy|LocalProxy))?|p(hinxClient|oofchecker|l(M(inHeap|axHeap)|S(tack|ubject)|Heap|T(ype|empFileObject)|Ob(server|jectStorage)|DoublyLinkedList|PriorityQueue|Enum|Queue|Fi(le(Info|Object)|xedArray)))|e(ssionHandler(Interface)?|ekableIterator|rializable)|DO_(Model_(ReflectionDataObject|Type|Property)|Sequence|D(ata(Object|Factory)|AS_(Relational|XML(_Document)?|Setting|ChangeSummary|Data(Object|Factory)))|Exception|List)|wish(Result(s)?|Search)?|VM(Model)?|QLite(Result|3(Result|Stmt)?|Database|Unbuffered)|AM(Message|Connection))|H(RTime\\\\(StopWatch|PerformanceCounter)|ttp(Re(sponse|quest(Pool)?)|Message|InflateStream|DeflateStream|QueryString)|aru(Image|Outline|D(oc|estination)|Page|Encoder|Font|Annotation))|Ya(f_(R(oute(_(Re(write|gex)|Map|S(tatic|imple|upervar)|Interface)|r)|e(sponse_Abstract|quest_(Simple|Http|Abstract)|gistry))|Session|Con(troller_Abstract|fig_(Simple|Ini|Abstract))|Dispatcher|Plugin_Abstract|Exception|View_(Simple|Interface)|Loader|A(ction_Abstract|pplication))|r_(Server(_Exception)?|C(oncurrent_Client|lient(_Exception)?)))|N(o(RewindIterator|rmalizer)|umberFormatter)|C(o(nd|untable|ll(ectable|ator))|URLFile|a(chingIterator|llbackFilterIterator))|T(hread(ed)?|okyoTyrant(Table|Iterator|Query)?|ra(nsliterator|versable))|I(n(tl(RuleBasedBreakIterator|BreakIterator|C(odePointBreakIterator|alendar)|TimeZone|Iterator|DateFormatter|PartsIterator)|validArgumentException|finiteIterator)|terator(Iterator|Aggregate)?|magick(Draw|Pixel(Iterator)?)?)|php_user_filter|Z(MQ(Socket|Context|Device|Poll)?|ipArchive)|O(CI-(Collection|Lob)|ut(erIterator|Of(RangeException|BoundsException))|verflowException)|D(irectory(Iterator)?|omainException|OM(XPath|N(ode(list)?|amedNodeMap)|C(haracterData|omment|dataSection)|Text|Implementation|Document(Fragment)?|ProcessingInstruction|E(ntityReference|lement)|Attr)|ate(Time(I(nterface|mmutable)|Zone)?|Interval|Period))|U(n(derflowException|expectedValueException)|Converter)|JsonSerializable|finfo|P(har(Data|FileInfo)?|ool|DO(Statement)?|arentIterator)|E(v(S(tat|ignal)|Ch(ild|eck)|Timer|I(o|dle)|ent(B(uffer(Event)?|ase)|SslContext|Http(Request|Connection)?|Config|DnsBase|Util|Listener)?|P(eriodic|repare)|Embed|Fork|Watcher|Loop)?|rrorException|xception|mptyIterator)|V(8Js(Exception)?|arnish(Stat|Log|Admin))|KTaglib_(MPEG_(File|AudioProperties)|Tag|ID3v2_(Tag|Frame|AttachedPictureFrame))|QuickHash(StringIntHash|Int(S(tringHash|et)|Hash))|F(il(terIterator|esystemIterator)|ANNConnection)|mysqli(_(stmt|driver|warning|result))?|W(orker|eak(Map|ref))|L(imitIterator|o(cale|gicException)|ua(Closure)?|engthException|apack)|A(ppendIterator|PCIterator|rray(Iterator|Object|Access)))\\b", + "name": "support.class.builtin.php" + } + ] + }, + "class-name": { + "patterns": [ + { + "begin": "(?i)(?=\\\\?[a-z_0-9]+\\\\)", + "end": "(?i)([a-z_][a-z_0-9]*)?(?=[^a-z0-9_\\\\])", + "endCaptures": { + "1": { + "name": "support.class.php" + } + }, + "patterns": [ + { + "include": "#namespace" + } + ] + }, + { + "include": "#class-builtin" + }, + { + "begin": "(?=[\\\\a-zA-Z_])", + "end": "(?i)([a-z_][a-z_0-9]*)?(?=[^a-z0-9_\\\\])", + "endCaptures": { + "1": { + "name": "support.class.php" + } + }, + "patterns": [ + { + "include": "#namespace" + } + ] + } + ] + }, + "comments": { + "patterns": [ + { + "begin": "/\\*\\*(?:#@\\+)?\\s*$", + "captures": { + "0": { + "name": "punctuation.definition.comment.php" + } + }, + "comment": "This now only highlights a docblock if the first line contains only /**\n\t\t\t\t\t\t\t\t- this is to stop highlighting everything as invalid when people do comment banners with /******** ...\n\t\t\t\t\t\t\t\t- Now matches /**#@+ too - used for docblock templates: http://manual.phpdoc.org/HTMLframesConverter/default/phpDocumentor/tutorial_phpDocumentor.howto.pkg.html#basics.docblocktemplate", + "end": "\\*/", + "name": "comment.block.documentation.phpdoc.php", + "patterns": [ + { + "include": "#php_doc" + } + ] + }, + { + "begin": "/\\*", + "captures": { + "0": { + "name": "punctuation.definition.comment.php" + } + }, + "end": "\\*/", + "name": "comment.block.php" + }, + { + "begin": "(^[ \\t]+)?(?=//)", + "beginCaptures": { + "1": { + "name": "punctuation.whitespace.comment.leading.php" + } + }, + "end": "(?!\\G)", + "patterns": [ + { + "begin": "//", + "beginCaptures": { + "0": { + "name": "punctuation.definition.comment.php" + } + }, + "end": "\\n|(?=\\?>)", + "name": "comment.line.double-slash.php" + } + ] + }, + { + "begin": "(^[ \\t]+)?(?=#)", + "beginCaptures": { + "1": { + "name": "punctuation.whitespace.comment.leading.php" + } + }, + "end": "(?!\\G)", + "patterns": [ + { + "begin": "#", + "beginCaptures": { + "0": { + "name": "punctuation.definition.comment.php" + } + }, + "end": "\\n|(?=\\?>)", + "name": "comment.line.number-sign.php" + } + ] + } + ] + }, + "constants": { + "patterns": [ + { + "begin": "(?xi)(?=\n\t\t\t (\n\t\t\t (\\\\[a-z_][a-z_0-9]*\\\\[a-z_][a-z_0-9\\\\]*)|\n\t\t\t ([a-z_][a-z_0-9]*\\\\[a-z_][a-z_0-9\\\\]*)\n\t\t\t )\n\t\t\t [^a-z_0-9\\\\])", + "end": "(?i)([a-z_][a-z_0-9]*)?(?=[^a-z0-9_\\\\])", + "endCaptures": { + "1": { + "name": "constant.other.php" + } + }, + "patterns": [ + { + "include": "#namespace" + } + ] + }, + { + "begin": "(?=\\\\?[a-zA-Z_\\x{7f}-\\x{ff}])", + "end": "(?=[^\\\\a-zA-Z_\\x{7f}-\\x{ff}])", + "patterns": [ + { + "match": "(?i)\\b(TRUE|FALSE|NULL|__(FILE|DIR|FUNCTION|CLASS|METHOD|LINE|NAMESPACE)__|ON|OFF|YES|NO|NL|BR|TAB)\\b", + "name": "constant.language.php" + }, + { + "captures": { + "1": { + "name": "punctuation.separator.inheritance.php" + } + }, + "match": "(\\\\)?\\b(STD(IN|OUT|ERR)|ZEND_(THREAD_SAFE|DEBUG_BUILD)|DEFAULT_INCLUDE_PATH|P(HP_(R(OUND_HALF_(ODD|DOWN|UP|EVEN)|ELEASE_VERSION)|M(INOR_VERSION|A(XPATHLEN|JOR_VERSION))|BINDIR|S(HLIB_SUFFIX|YSCONFDIR|API)|CONFIG_FILE_(SCAN_DIR|PATH)|INT_(MAX|SIZE)|ZTS|O(S|UTPUT_HANDLER_(START|CONT|END))|D(EBUG|ATADIR)|URL_(SCHEME|HOST|USER|P(ORT|A(SS|TH))|QUERY|FRAGMENT)|PREFIX|E(XT(RA_VERSION|ENSION_DIR)|OL)|VERSION(_ID)?|WINDOWS_(NT_(SERVER|DOMAIN_CONTROLLER|WORKSTATION)|VERSION_(M(INOR|AJOR)|BUILD|S(UITEMASK|P_M(INOR|AJOR))|P(RODUCTTYPE|LATFORM)))|L(IBDIR|OCALSTATEDIR))|EAR_(INSTALL_DIR|EXTENSION_DIR))|E_(RECOVERABLE_ERROR|STRICT|NOTICE|CO(RE_(ERROR|WARNING)|MPILE_(ERROR|WARNING))|DEPRECATED|USER_(NOTICE|DEPRECATED|ERROR|WARNING)|PARSE|ERROR|WARNING|ALL))\\b", + "name": "support.constant.core.php" + }, + { + "captures": { + "1": { + "name": "punctuation.separator.inheritance.php" + } + }, + "match": "(\\\\)?\\b(RADIXCHAR|GROUPING|M(_(1_PI|SQRT(1_2|2|3|PI)|2_(SQRTPI|PI)|PI(_(2|4))?|E(ULER)?|L(N(10|2|PI)|OG(10E|2E)))|ON_(GROUPING|1(1|2|0)?|7|2|8|THOUSANDS_SEP|3|DECIMAL_POINT|9|4|5|6))|S(TR_PAD_(RIGHT|BOTH|LEFT)|ORT_(REGULAR|STRING|NUMERIC|DESC|LOCALE_STRING|ASC)|EEK_(SET|CUR|END))|H(TML_(SPECIALCHARS|ENTITIES)|ASH_HMAC)|YES(STR|EXPR)|N(_(S(IGN_POSN|EP_BY_SPACE)|CS_PRECEDES)|O(STR|EXPR)|EGATIVE_SIGN|AN)|C(R(YPT_(MD5|BLOWFISH|S(HA(256|512)|TD_DES|ALT_LENGTH)|EXT_DES)|NCYSTR|EDITS_(G(ROUP|ENERAL)|MODULES|SAPI|DOCS|QA|FULLPAGE|ALL))|HAR_MAX|O(NNECTION_(NORMAL|TIMEOUT|ABORTED)|DESET|UNT_(RECURSIVE|NORMAL))|URRENCY_SYMBOL|ASE_(UPPER|LOWER))|__COMPILER_HALT_OFFSET__|T(HOUS(EP|ANDS_SEP)|_FMT(_AMPM)?)|IN(T_(CURR_SYMBOL|FRAC_DIGITS)|I_(S(YSTEM|CANNER_(RAW|NORMAL))|USER|PERDIR|ALL)|F(O_(GENERAL|MODULES|C(REDITS|ONFIGURATION)|ENVIRONMENT|VARIABLES|LICENSE|ALL))?)|D(_(T_FMT|FMT)|IRECTORY_SEPARATOR|ECIMAL_POINT|A(Y_(1|7|2|3|4|5|6)|TE_(R(SS|FC(1(123|036)|2822|8(22|50)|3339))|COOKIE|ISO8601|W3C|ATOM)))|UPLOAD_ERR_(NO_(TMP_DIR|FILE)|CANT_WRITE|INI_SIZE|OK|PARTIAL|EXTENSION|FORM_SIZE)|P(M_STR|_(S(IGN_POSN|EP_BY_SPACE)|CS_PRECEDES)|OSITIVE_SIGN|ATH(_SEPARATOR|INFO_(BASENAME|DIRNAME|EXTENSION|FILENAME)))|E(RA(_(YEAR|T_FMT|D_(T_FMT|FMT)))?|XTR_(REFS|SKIP|IF_EXISTS|OVERWRITE|PREFIX_(SAME|I(NVALID|F_EXISTS)|ALL))|NT_(NOQUOTES|COMPAT|IGNORE|QUOTES))|FRAC_DIGITS|L(C_(M(ONETARY|ESSAGES)|NUMERIC|C(TYPE|OLLATE)|TIME|ALL)|O(G_(MAIL|SYSLOG|N(O(TICE|WAIT)|DELAY|EWS)|C(R(IT|ON)|ONS)|INFO|ODELAY|D(EBUG|AEMON)|U(SER|UCP)|P(ID|ERROR)|E(RR|MERG)|KERN|WARNING|L(OCAL(1|7|2|3|4|5|0|6)|PR)|A(UTH(PRIV)?|LERT))|CK_(SH|NB|UN|EX)))|A(M_STR|B(MON_(1(1|2|0)?|7|2|8|3|9|4|5|6)|DAY_(1|7|2|3|4|5|6))|SSERT_(BAIL|CALLBACK|QUIET_EVAL|WARNING|ACTIVE)|LT_DIGITS))\\b", + "name": "support.constant.std.php" + }, + { + "captures": { + "1": { + "name": "punctuation.separator.inheritance.php" + } + }, + "match": "(\\\\)?\\b(GLOB_(MARK|BRACE|NO(SORT|CHECK|ESCAPE)|ONLYDIR|ERR|AVAILABLE_FLAGS)|XML_(SAX_IMPL|HTML_DOCUMENT_NODE|N(OTATION_NODE|AMESPACE_DECL_NODE)|C(OMMENT_NODE|DATA_SECTION_NODE)|TEXT_NODE|OPTION_(SKIP_(TAGSTART|WHITE)|CASE_FOLDING|TARGET_ENCODING)|D(TD_NODE|OCUMENT_(NODE|TYPE_NODE|FRAG_NODE))|PI_NODE|E(RROR_(RECURSIVE_ENTITY_REF|MISPLACED_XML_PI|B(INARY_ENTITY_REF|AD_CHAR_REF)|SYNTAX|NO(NE|_(MEMORY|ELEMENTS))|TAG_MISMATCH|IN(CORRECT_ENCODING|VALID_TOKEN)|DUPLICATE_ATTRIBUTE|UN(CLOSED_(CDATA_SECTION|TOKEN)|DEFINED_ENTITY|KNOWN_ENCODING)|JUNK_AFTER_DOC_ELEMENT|PAR(TIAL_CHAR|AM_ENTITY_REF)|EXTERNAL_ENTITY_HANDLING|A(SYNC_ENTITY|TTRIBUTE_EXTERNAL_ENTITY_REF))|NTITY_(REF_NODE|NODE|DECL_NODE)|LEMENT_(NODE|DECL_NODE))|LOCAL_NAMESPACE|ATTRIBUTE_(N(MTOKEN(S)?|O(TATION|DE))|CDATA|ID(REF(S)?)?|DECL_NODE|EN(TITY|UMERATION)))|M(HASH_(RIPEMD(1(28|60)|256|320)|GOST|MD(2|4|5)|S(HA(1|2(24|56)|384|512)|NEFRU256)|HAVAL(1(28|92|60)|2(24|56))|CRC32(B)?|TIGER(1(28|60))?|WHIRLPOOL|ADLER32)|YSQL(_(BOTH|NUM|CLIENT_(SSL|COMPRESS|I(GNORE_SPACE|NTERACTIVE))|ASSOC)|I_(RE(PORT_(STRICT|INDEX|OFF|ERROR|ALL)|FRESH_(GRANT|MASTER|BACKUP_LOG|S(TATUS|LAVE)|HOSTS|T(HREADS|ABLES)|LOG)|AD_DEFAULT_(GROUP|FILE))|GROUP_FLAG|MULTIPLE_KEY_FLAG|B(INARY_FLAG|OTH|LOB_FLAG)|S(T(MT_ATTR_(CURSOR_TYPE|UPDATE_MAX_LENGTH|PREFETCH_ROWS)|ORE_RESULT)|E(RVER_QUERY_(NO_(GOOD_INDEX_USED|INDEX_USED)|WAS_SLOW)|T_(CHARSET_NAME|FLAG)))|N(O(_D(EFAULT_VALUE_FLAG|ATA)|T_NULL_FLAG)|UM(_FLAG)?)|C(URSOR_TYPE_(READ_ONLY|SCROLLABLE|NO_CURSOR|FOR_UPDATE)|LIENT_(SSL|NO_SCHEMA|COMPRESS|I(GNORE_SPACE|NTERACTIVE)|FOUND_ROWS))|T(YPE_(GEOMETRY|MEDIUM_BLOB|B(IT|LOB)|S(HORT|TRING|ET)|YEAR|N(ULL|EWD(ECIMAL|ATE))|CHAR|TI(ME(STAMP)?|NY(_BLOB)?)|INT(24|ERVAL)|D(OUBLE|ECIMAL|ATE(TIME)?)|ENUM|VAR_STRING|FLOAT|LONG(_BLOB|LONG)?)|IMESTAMP_FLAG)|INIT_COMMAND|ZEROFILL_FLAG|O(N_UPDATE_NOW_FLAG|PT_(NET_(READ_BUFFER_SIZE|CMD_BUFFER_SIZE)|CONNECT_TIMEOUT|INT_AND_FLOAT_NATIVE|LOCAL_INFILE))|D(EBUG_TRACE_ENABLED|ATA_TRUNCATED)|U(SE_RESULT|N(SIGNED_FLAG|IQUE_KEY_FLAG))|P(RI_KEY_FLAG|ART_KEY_FLAG)|ENUM_FLAG|A(S(SOC|YNC)|UTO_INCREMENT_FLAG)))|CRYPT_(R(C(2|6)|IJNDAEL_(1(28|92)|256)|AND)|GOST|XTEA|M(ODE_(STREAM|NOFB|C(BC|FB)|OFB|ECB)|ARS)|BLOWFISH(_COMPAT)?|S(ERPENT|KIPJACK|AFER(128|PLUS|64))|C(RYPT|AST_(128|256))|T(RIPLEDES|HREEWAY|WOFISH)|IDEA|3DES|DE(S|CRYPT|V_(RANDOM|URANDOM))|PANAMA|EN(CRYPT|IGNA)|WAKE|LOKI97|ARCFOUR(_IV)?))|S(TREAM_(REPORT_ERRORS|M(UST_SEEK|KDIR_RECURSIVE)|BUFFER_(NONE|FULL|LINE)|S(HUT_(RD(WR)?|WR)|OCK_(R(DM|AW)|S(TREAM|EQPACKET)|DGRAM)|ERVER_(BIND|LISTEN))|NOTIFY_(RE(SOLVE|DIRECTED)|MIME_TYPE_IS|SEVERITY_(INFO|ERR|WARN)|CO(MPLETED|NNECT)|PROGRESS|F(ILE_SIZE_IS|AILURE)|AUTH_RE(SULT|QUIRED))|C(RYPTO_METHOD_(SSLv(2(_(SERVER|CLIENT)|3_(SERVER|CLIENT))|3_(SERVER|CLIENT))|TLS_(SERVER|CLIENT))|LIENT_(CONNECT|PERSISTENT|ASYNC_CONNECT)|AST_(FOR_SELECT|AS_STREAM))|I(GNORE_URL|S_URL|PPROTO_(RAW|TCP|I(CMP|P)|UDP))|O(OB|PTION_(READ_(BUFFER|TIMEOUT)|BLOCKING|WRITE_BUFFER))|U(RL_STAT_(QUIET|LINK)|SE_PATH)|P(EEK|F_(INET(6)?|UNIX))|ENFORCE_SAFE_MODE|FILTER_(READ|WRITE|ALL))|UNFUNCS_RET_(STRING|TIMESTAMP|DOUBLE)|QLITE(_(R(OW|EADONLY)|MIS(MATCH|USE)|B(OTH|USY)|SCHEMA|N(O(MEM|T(FOUND|ADB)|LFS)|UM)|C(O(RRUPT|NSTRAINT)|ANTOPEN)|TOOBIG|I(NTER(RUPT|NAL)|OERR)|OK|DONE|P(ROTOCOL|ERM)|E(RROR|MPTY)|F(ORMAT|ULL)|LOCKED|A(BORT|SSOC|UTH))|3_(B(OTH|LOB)|NU(M|LL)|TEXT|INTEGER|OPEN_(READ(ONLY|WRITE)|CREATE)|FLOAT|ASSOC)))|CURL(M(SG_DONE|_(BAD_(HANDLE|EASY_HANDLE)|CALL_MULTI_PERFORM|INTERNAL_ERROR|O(UT_OF_MEMORY|K)))|SSH_AUTH_(HOST|NONE|DEFAULT|P(UBLICKEY|ASSWORD)|KEYBOARD)|CLOSEPOLICY_(SLOWEST|CALLBACK|OLDEST|LEAST_(RECENTLY_USED|TRAFFIC))|_(HTTP_VERSION_(1_(1|0)|NONE)|NETRC_(REQUIRED|IGNORED|OPTIONAL)|TIMECOND_(IF(MODSINCE|UNMODSINCE)|LASTMOD)|IPRESOLVE_(V(4|6)|WHATEVER)|VERSION_(SSL|IPV6|KERBEROS4|LIBZ))|INFO_(RE(DIRECT_(COUNT|TIME)|QUEST_SIZE)|S(SL_VERIFYRESULT|TARTTRANSFER_TIME|IZE_(DOWNLOAD|UPLOAD)|PEED_(DOWNLOAD|UPLOAD))|H(TTP_CODE|EADER_(SIZE|OUT))|NAMELOOKUP_TIME|C(ON(NECT_TIME|TENT_(TYPE|LENGTH_(DOWNLOAD|UPLOAD)))|ERTINFO)|TOTAL_TIME|PR(IVATE|ETRANSFER_TIME)|EFFECTIVE_URL|FILETIME)|OPT_(R(E(SUME_FROM|TURNTRANSFER|DIR_PROTOCOLS|FERER|AD(DATA|FUNCTION))|AN(GE|DOM_FILE))|MAX(REDIRS|CONNECTS)|B(INARYTRANSFER|UFFERSIZE)|S(S(H_(HOST_PUBLIC_KEY_MD5|P(RIVATE_KEYFILE|UBLIC_KEYFILE)|AUTH_TYPES)|L(CERT(TYPE|PASSWD)?|_(CIPHER_LIST|VERIFY(HOST|PEER))|ENGINE(_DEFAULT)?|VERSION|KEY(TYPE|PASSWD)?))|TDERR)|H(TTP(GET|HEADER|200ALIASES|_VERSION|PROXYTUNNEL|AUTH)|EADER(FUNCTION)?)|N(O(BODY|SIGNAL|PROGRESS)|ETRC)|C(RLF|O(NNECTTIMEOUT(_MS)?|OKIE(SESSION|JAR|FILE)?)|USTOMREQUEST|ERTINFO|LOSEPOLICY|A(INFO|PATH))|T(RANSFERTEXT|CP_NODELAY|IME(CONDITION|OUT(_MS)?|VALUE))|I(N(TERFACE|FILE(SIZE)?)|PRESOLVE)|DNS_(CACHE_TIMEOUT|USE_GLOBAL_CACHE)|U(RL|SER(PWD|AGENT)|NRESTRICTED_AUTH|PLOAD)|P(R(IVATE|O(GRESSFUNCTION|XY(TYPE|USERPWD|PORT|AUTH)?|TOCOLS))|O(RT|ST(REDIR|QUOTE|FIELDS)?)|UT)|E(GDSOCKET|NCODING)|VERBOSE|K(RB4LEVEL|EYPASSWD)|QUOTE|F(RESH_CONNECT|TP(SSLAUTH|_(S(SL|KIP_PASV_IP)|CREATE_MISSING_DIRS|USE_EP(RT|SV)|FILEMETHOD)|PORT|LISTONLY|APPEND)|ILE(TIME)?|O(RBID_REUSE|LLOWLOCATION)|AILONERROR)|WRITE(HEADER|FUNCTION)|LOW_SPEED_(TIME|LIMIT)|AUTOREFERER)|PRO(XY_(SOCKS(4|5)|HTTP)|TO_(S(CP|FTP)|HTTP(S)?|T(ELNET|FTP)|DICT|F(TP(S)?|ILE)|LDAP(S)?|ALL))|E_(RE(CV_ERROR|AD_ERROR)|GOT_NOTHING|MALFORMAT_USER|BAD_(C(ONTENT_ENCODING|ALLING_ORDER)|PASSWORD_ENTERED|FUNCTION_ARGUMENT)|S(S(H|L_(C(IPHER|ONNECT_ERROR|ERTPROBLEM|ACERT)|PEER_CERTIFICATE|ENGINE_(SETFAILED|NOTFOUND)))|HARE_IN_USE|END_ERROR)|HTTP_(RANGE_ERROR|NOT_FOUND|PO(RT_FAILED|ST_ERROR))|COULDNT_(RESOLVE_(HOST|PROXY)|CONNECT)|T(OO_MANY_REDIRECTS|ELNET_OPTION_SYNTAX)|O(BSOLETE|UT_OF_MEMORY|PERATION_TIMEOUTED|K)|U(RL_MALFORMAT(_USER)?|N(SUPPORTED_PROTOCOL|KNOWN_TELNET_OPTION))|PARTIAL_FILE|F(TP_(BAD_DOWNLOAD_RESUME|SSL_FAILED|C(OULDNT_(RETR_FILE|GET_SIZE|S(TOR_FILE|ET_(BINARY|ASCII))|USE_REST)|ANT_(RECONNECT|GET_HOST))|USER_PASSWORD_INCORRECT|PORT_FAILED|QUOTE_ERROR|W(RITE_ERROR|EIRD_(SERVER_REPLY|227_FORMAT|USER_REPLY|PAS(S_REPLY|V_REPLY)))|ACCESS_DENIED)|ILE(SIZE_EXCEEDED|_COULDNT_READ_FILE)|UNCTION_NOT_FOUND|AILED_INIT)|WRITE_ERROR|L(IBRARY_NOT_FOUND|DAP_(SEARCH_FAILED|CANNOT_BIND|INVALID_URL))|ABORTED_BY_CALLBACK)|VERSION_NOW|FTP(METHOD_(MULTICWD|SINGLECWD|NOCWD)|SSL_(NONE|CONTROL|TRY|ALL)|AUTH_(SSL|TLS|DEFAULT))|AUTH_(GSSNEGOTIATE|BASIC|NTLM|DIGEST|ANY(SAFE)?))|I(MAGETYPE_(GIF|XBM|BMP|SWF|COUNT|TIFF_(MM|II)|I(CO|FF)|UNKNOWN|J(B2|P(X|2|C|EG(2000)?))|P(SD|NG)|WBMP)|NPUT_(REQUEST|GET|SE(RVER|SSION)|COOKIE|POST|ENV)|CONV_(MIME_DECODE_(STRICT|CONTINUE_ON_ERROR)|IMPL|VERSION))|D(NS_(MX|S(RV|OA)|HINFO|N(S|APTR)|CNAME|TXT|PTR|A(NY|LL|AAA|6)?)|OM(STRING_SIZE_ERR|_(SYNTAX_ERR|HIERARCHY_REQUEST_ERR|N(O(_(MODIFICATION_ALLOWED_ERR|DATA_ALLOWED_ERR)|T_(SUPPORTED_ERR|FOUND_ERR))|AMESPACE_ERR)|IN(DEX_SIZE_ERR|USE_ATTRIBUTE_ERR|VALID_(MODIFICATION_ERR|STATE_ERR|CHARACTER_ERR|ACCESS_ERR))|PHP_ERR|VALIDATION_ERR|WRONG_DOCUMENT_ERR)))|JSON_(HEX_(TAG|QUOT|A(MP|POS))|NUMERIC_CHECK|ERROR_(S(YNTAX|TATE_MISMATCH)|NONE|CTRL_CHAR|DEPTH|UTF8)|FORCE_OBJECT)|P(REG_(RECURSION_LIMIT_ERROR|GREP_INVERT|BA(CKTRACK_LIMIT_ERROR|D_UTF8_(OFFSET_ERROR|ERROR))|S(PLIT_(NO_EMPTY|OFFSET_CAPTURE|DELIM_CAPTURE)|ET_ORDER)|NO_ERROR|INTERNAL_ERROR|OFFSET_CAPTURE|PATTERN_ORDER)|SFS_(PASS_ON|ERR_FATAL|F(EED_ME|LAG_(NORMAL|FLUSH_(CLOSE|INC))))|CRE_VERSION|OSIX_(R_OK|X_OK|S_IF(REG|BLK|SOCK|CHR|IFO)|F_OK|W_OK))|F(NM_(NOESCAPE|CASEFOLD|P(ERIOD|ATHNAME))|IL(TER_(REQUIRE_(SCALAR|ARRAY)|SANITIZE_(MAGIC_QUOTES|S(TRI(NG|PPED)|PECIAL_CHARS)|NUMBER_(INT|FLOAT)|URL|E(MAIL|NCODED)|FULL_SPECIAL_CHARS)|NULL_ON_FAILURE|CALLBACK|DEFAULT|UNSAFE_RAW|VALIDATE_(REGEXP|BOOLEAN|I(NT|P)|URL|EMAIL|FLOAT)|F(ORCE_ARRAY|LAG_(S(CHEME_REQUIRED|TRIP_(BACKTICK|HIGH|LOW))|HOST_REQUIRED|NO(NE|_(RES_RANGE|PRIV_RANGE|ENCODE_QUOTES))|IPV(4|6)|PATH_REQUIRED|E(MPTY_STRING_NULL|NCODE_(HIGH|LOW|AMP))|QUERY_REQUIRED|ALLOW_(SCIENTIFIC|HEX|THOUSAND|OCTAL|FRACTION))))|E(_(BINARY|SKIP_EMPTY_LINES|NO_DEFAULT_CONTEXT|TEXT|IGNORE_NEW_LINES|USE_INCLUDE_PATH|APPEND)|INFO_(RAW|MIME(_(TYPE|ENCODING))?|SYMLINK|NONE|CONTINUE|DEVICES|PRESERVE_ATIME)))|ORCE_(GZIP|DEFLATE))|LIBXML_(XINCLUDE|N(SCLEAN|O(XMLDECL|BLANKS|NET|CDATA|E(RROR|MPTYTAG|NT)|WARNING))|COMPACT|D(TD(VALID|LOAD|ATTR)|OTTED_VERSION)|PARSEHUGE|ERR_(NONE|ERROR|FATAL|WARNING)|VERSION|LOADED_VERSION))\\b", + "name": "support.constant.ext.php" + }, + { + "captures": { + "1": { + "name": "punctuation.separator.inheritance.php" + } + }, + "match": "(\\\\)?\\bT_(RE(TURN|QUIRE(_ONCE)?)|G(OTO|LOBAL)|XOR_EQUAL|M(INUS_EQUAL|OD_EQUAL|UL_EQUAL|ETHOD_C|L_COMMENT)|B(REAK|OOL(_CAST|EAN_(OR|AND))|AD_CHARACTER)|S(R(_EQUAL)?|T(RING(_(CAST|VARNAME))?|A(RT_HEREDOC|TIC))|WITCH|L(_EQUAL)?)|HALT_COMPILER|N(S_(SEPARATOR|C)|UM_STRING|EW|AMESPACE)|C(HARACTER|O(MMENT|N(ST(ANT_ENCAPSED_STRING)?|CAT_EQUAL|TINUE))|URLY_OPEN|L(O(SE_TAG|NE)|ASS(_C)?)|A(SE|TCH))|T(RY|HROW)|I(MPLEMENTS|S(SET|_(GREATER_OR_EQUAL|SMALLER_OR_EQUAL|NOT_(IDENTICAL|EQUAL)|IDENTICAL|EQUAL))|N(STANCEOF|C(LUDE(_ONCE)?)?|T(_CAST|ERFACE)|LINE_HTML)|F)|O(R_EQUAL|BJECT_(CAST|OPERATOR)|PEN_TAG(_WITH_ECHO)?|LD_FUNCTION)|D(NUMBER|I(R|V_EQUAL)|O(C_COMMENT|UBLE_(C(OLON|AST)|ARROW)|LLAR_OPEN_CURLY_BRACES)?|E(C(LARE)?|FAULT))|U(SE|NSET(_CAST)?)|P(R(I(NT|VATE)|OTECTED)|UBLIC|LUS_EQUAL|AAMAYIM_NEKUDOTAYIM)|E(X(TENDS|IT)|MPTY|N(CAPSED_AND_WHITESPACE|D(SWITCH|_HEREDOC|IF|DECLARE|FOR(EACH)?|WHILE))|CHO|VAL|LSE(IF)?)|VAR(IABLE)?|F(I(NAL|LE)|OR(EACH)?|UNC(_C|TION))|WHI(TESPACE|LE)|L(NUMBER|I(ST|NE)|OGICAL_(XOR|OR|AND))|A(RRAY(_CAST)?|BSTRACT|S|ND_EQUAL))\\b", + "name": "support.constant.parser-token.php" + }, + { + "comment": "In PHP, any identifier which is not a variable is taken to be a constant.\n \t\t\t\tHowever, if there is no constant defined with the given name then a notice\n \t\t\t\tis generated and the constant is assumed to have the value of its name.", + "match": "[a-zA-Z_\\x{7f}-\\x{ff}][a-zA-Z0-9_\\x{7f}-\\x{ff}]*", + "name": "constant.other.php" + } + ] + } + ] + }, + "function-arguments": { + "patterns": [ + { + "include": "#comments" + }, + { + "begin": "(?xi)\n\t\t\t\t\t\t\t\\s*(array) # Typehint\n\t\t\t\t\t\t\t\\s*(&)? \t\t\t\t\t# Reference\n\t\t\t\t\t\t\t\\s*((\\$+)[a-zA-Z_\\x{7f}-\\x{ff}][a-zA-Z0-9_\\x{7f}-\\x{ff}]*) # The variable name\n\t\t\t\t\t\t\t\\s*(=)\t# A default value\n\t\t\t\t\t\t\t\\s*(array)\\s*(\\()\n\t\t\t\t\t\t\t", + "beginCaptures": { + "1": { + "name": "storage.type.php" + }, + "2": { + "name": "storage.modifier.reference.php" + }, + "3": { + "name": "variable.other.php" + }, + "4": { + "name": "punctuation.definition.variable.php" + }, + "5": { + "name": "keyword.operator.assignment.php" + }, + "6": { + "name": "support.function.construct.php" + }, + "7": { + "name": "punctuation.definition.array.begin.php" + } + }, + "contentName": "meta.array.php", + "end": "\\)", + "endCaptures": { + "0": { + "name": "punctuation.definition.array.end.php" + } + }, + "name": "meta.function.argument.array.php", + "patterns": [ + { + "include": "#comments" + }, + { + "include": "#strings" + }, + { + "include": "#numbers" + } + ] + }, + { + "captures": { + "1": { + "name": "storage.type.php" + }, + "2": { + "name": "storage.modifier.reference.php" + }, + "3": { + "name": "variable.other.php" + }, + "4": { + "name": "punctuation.definition.variable.php" + }, + "5": { + "name": "keyword.operator.assignment.php" + }, + "6": { + "name": "constant.language.php" + }, + "7": { + "name": "punctuation.section.array.begin.php" + }, + "8": { + "patterns": [ + { + "include": "#parameter-default-types" + } + ] + }, + "9": { + "name": "punctuation.section.array.end.php" + }, + "10": { + "name": "invalid.illegal.non-null-typehinted.php" + } + }, + "match": "(?xi)\n\t\t\t\t\t\t\t\\s*(array|callable) # Typehint\n\t\t\t\t\t\t\t\\s*(&)? \t\t\t\t\t# Reference\n\t\t\t\t\t\t\t\\s*((\\$+)[a-z_\\x{7f}-\\x{ff}][a-z0-9_\\x{7f}-\\x{ff}]*) # The variable name\n\t\t\t\t\t\t\t(?:\n\t\t\t\t\t\t\t\t\\s*(?:(=)\\s*(?:(null)|(\\[)((?>[^\\[\\]]+|\\[\\g<8>\\])*)(\\])|((?:\\S*?\\(\\))|(?:\\S*?))))\t# A default value\n\t\t\t\t\t\t\t)?\n\t\t\t\t\t\t\t\\s*(?=,|\\)|/[/*]|\\#|$) # A closing parentheses (end of argument list) or a comma or a comment\n\t\t\t\t\t\t\t", + "name": "meta.function.argument.array.php" + }, + { + "begin": "(?i)(?=[a-z_0-9\\\\]*[a-z_][a-z_0-9]*\\s*&?\\s*(?:\\.\\.\\.)?\\$)", + "end": "(?=,|\\)|/[/*]|\\#|$)", + "name": "meta.function.argument.typehinted.php", + "patterns": [ + { + "include": "#class-name" + }, + { + "captures": { + "1": { + "name": "support.class.php" + }, + "2": { + "name": "storage.modifier.reference.php" + }, + "3": { + "name": "variable.other.php" + }, + "4": { + "name": "punctuation.definition.variable.php" + }, + "5": { + "name": "keyword.operator.assignment.php" + }, + "6": { + "name": "constant.language.php" + }, + "7": { + "name": "invalid.illegal.non-null-typehinted.php" + } + }, + "match": "(?xi)\n \t\t\t\t\t\t\t\\s*([a-z_][a-z_0-9]*)? # Typehinted class name\n \t\t\t\t\t\t\t\\s*(&)? \t\t\t\t\t# Reference\n \t\t\t\t\t\t\t\\s*(((?:\\.\\.\\.)?\\$+)[a-z_\\x{7f}-\\x{ff}][a-z0-9_\\x{7f}-\\x{ff}]*) # The variable name\n \t\t\t\t\t\t\t(?:\n \t\t\t\t\t\t\t\t\\s*(?:(=)\\s*(?:(null)|((?:\\S*?\\(\\))|(?:\\S*?))))\t# A default value\n \t\t\t\t\t\t\t)?\n \t\t\t\t\t\t\t\\s*(?=,|\\)|/[/*]|\\#|$) # A closing parentheses (end of argument list) or a comma\n\t\t\t\t\t " + } + ] + }, + { + "captures": { + "1": { + "name": "storage.modifier.reference.php" + }, + "2": { + "name": "variable.other.php" + }, + "3": { + "name": "punctuation.definition.variable.php" + } + }, + "match": "(?:\\s*(&))?\\s*(((?:\\.\\.\\.)?\\$+)[a-zA-Z_\\x{7f}-\\x{ff}][a-zA-Z0-9_\\x{7f}-\\x{ff}]*)\\s*(?=,|\\)|/[/*]|\\#)", + "name": "meta.function.argument.no-default.php" + }, + { + "begin": "(?:\\s*(&))?\\s*((\\$+)[a-zA-Z_\\x{7f}-\\x{ff}][a-zA-Z0-9_\\x{7f}-\\x{ff}]*)(?:\\s*(=)\\s*)\\s*(?:(\\[)((?>[^\\[\\]]+|\\[\\g<6>\\])*)(\\]))?", + "captures": { + "1": { + "name": "storage.modifier.reference.php" + }, + "2": { + "name": "variable.other.php" + }, + "3": { + "name": "punctuation.definition.variable.php" + }, + "4": { + "name": "keyword.operator.assignment.php" + }, + "5": { + "name": "punctuation.section.array.begin.php" + }, + "6": { + "patterns": [ + { + "include": "#parameter-default-types" + } + ] + }, + "7": { + "name": "punctuation.section.array.end.php" + } + }, + "end": "(?=,|\\)|/[/*]|\\#)", + "name": "meta.function.argument.default.php", + "patterns": [ + { + "include": "#parameter-default-types" + } + ] + } + ] + }, + "function-call": { + "patterns": [ + { + "begin": "(?i)(?=\\\\?[a-z_0-9\\\\]+\\\\[a-z_][a-z0-9_]*\\s*\\()", + "comment": "Functions in a user-defined namespace (overrides any built-ins)", + "end": "(?=\\s*\\()", + "patterns": [ + { + "include": "#user-function-call" + } + ] + }, + { + "match": "(?i)\\b(print|echo)\\b", + "name": "support.function.construct.output.php" + }, + { + "begin": "(?i)(\\\\)?(?=\\b[a-z_][a-z_0-9]*\\s*\\()", + "beginCaptures": { + "1": { + "name": "punctuation.separator.inheritance.php" + } + }, + "comment": "Root namespace function calls (built-in or user)", + "end": "(?=\\s*\\()", + "patterns": [ + { + "match": "(?i)\\b(isset|unset|e(val|mpty)|list)(?=\\s*\\()", + "name": "support.function.construct.php" + }, + { + "include": "#support" + }, + { + "include": "#user-function-call" + } + ] + } + ] + }, + "heredoc": { + "patterns": [ + { + "begin": "(?=<<<\\s*(\"?)([a-zA-Z_]+[a-zA-Z0-9_]*)(\\1)\\s*$)", + "end": "(?!\\G)", + "injections": { + "*": { + "patterns": [ + { + "include": "#interpolation" + } + ] + } + }, + "name": "string.unquoted.heredoc.php", + "patterns": [ + { + "include": "#heredoc_interior" + } + ] + }, + { + "begin": "(?=<<<\\s*('?)([a-zA-Z_]+[a-zA-Z0-9_]*)(\\1)\\s*$)", + "end": "(?!\\G)", + "name": "string.unquoted.heredoc.nowdoc.php", + "patterns": [ + { + "include": "#heredoc_interior" + } + ] + } + ], + "repository": { + "heredoc_interior": { + "patterns": [ + { + "begin": "(<<<)\\s*(['\"]?)(HTML)(\\2)\\s*$\\n?", + "beginCaptures": { + "0": { + "name": "punctuation.section.embedded.begin.php" + }, + "1": { + "name": "punctuation.definition.string.php" + }, + "3": { + "name": "keyword.operator.heredoc.php" + } + }, + "contentName": "text.html", + "end": "^(\\3)\\b", + "endCaptures": { + "0": { + "name": "punctuation.section.embedded.end.php" + }, + "1": { + "name": "keyword.operator.heredoc.php" + } + }, + "name": "meta.embedded.html", + "patterns": [ + { + "include": "text.html.basic" + } + ] + }, + { + "begin": "(<<<)\\s*(['\"]?)(XML)(\\2)\\s*$\\n?", + "beginCaptures": { + "0": { + "name": "punctuation.section.embedded.begin.php" + }, + "1": { + "name": "punctuation.definition.string.php" + }, + "3": { + "name": "keyword.operator.heredoc.php" + } + }, + "contentName": "text.xml", + "end": "^(\\3)\\b", + "endCaptures": { + "0": { + "name": "punctuation.section.embedded.end.php" + }, + "1": { + "name": "keyword.operator.heredoc.php" + } + }, + "name": "meta.embedded.xml", + "patterns": [ + { + "include": "text.xml" + } + ] + }, + { + "begin": "(<<<)\\s*(['\"]?)(SQL)(\\2)\\s*$\\n?", + "beginCaptures": { + "0": { + "name": "punctuation.section.embedded.begin.php" + }, + "1": { + "name": "punctuation.definition.string.php" + }, + "3": { + "name": "keyword.operator.heredoc.php" + } + }, + "contentName": "source.sql", + "end": "^(\\3)\\b", + "endCaptures": { + "0": { + "name": "punctuation.section.embedded.end.php" + }, + "1": { + "name": "keyword.operator.heredoc.php" + } + }, + "name": "meta.embedded.sql", + "patterns": [ + { + "include": "source.sql" + } + ] + }, + { + "begin": "(<<<)\\s*(['\"]?)(JAVASCRIPT)(\\2)\\s*$\\n?", + "beginCaptures": { + "0": { + "name": "punctuation.section.embedded.begin.php" + }, + "1": { + "name": "punctuation.definition.string.php" + }, + "3": { + "name": "keyword.operator.heredoc.php" + } + }, + "contentName": "source.js", + "end": "^(\\3)\\b", + "endCaptures": { + "0": { + "name": "punctuation.section.embedded.end.php" + }, + "1": { + "name": "keyword.operator.heredoc.php" + } + }, + "name": "meta.embedded.js", + "patterns": [ + { + "include": "source.js" + } + ] + }, + { + "begin": "(<<<)\\s*(['\"]?)(JSON)(\\2)\\s*$\\n?", + "beginCaptures": { + "0": { + "name": "punctuation.section.embedded.begin.php" + }, + "1": { + "name": "punctuation.definition.string.php" + }, + "3": { + "name": "keyword.operator.heredoc.php" + } + }, + "contentName": "source.json", + "end": "^(\\3)\\b", + "endCaptures": { + "0": { + "name": "punctuation.section.embedded.end.php" + }, + "1": { + "name": "keyword.operator.heredoc.php" + } + }, + "name": "meta.embedded.json", + "patterns": [ + { + "include": "source.json" + } + ] + }, + { + "begin": "(<<<)\\s*(['\"]?)(CSS)(\\2)\\s*$\\n?", + "beginCaptures": { + "0": { + "name": "punctuation.section.embedded.begin.php" + }, + "1": { + "name": "punctuation.definition.string.php" + }, + "3": { + "name": "keyword.operator.heredoc.php" + } + }, + "contentName": "source.css", + "end": "^(\\3)\\b", + "endCaptures": { + "0": { + "name": "punctuation.section.embedded.end.php" + }, + "1": { + "name": "keyword.operator.heredoc.php" + } + }, + "name": "meta.embedded.css", + "patterns": [ + { + "include": "source.css" + } + ] + }, + { + "begin": "(<<<)\\s*(['\"]?)(REGEX)(\\2)\\s*$\\n?", + "beginCaptures": { + "0": { + "name": "punctuation.section.embedded.begin.php" + }, + "1": { + "name": "punctuation.definition.string.php" + }, + "3": { + "name": "keyword.operator.heredoc.php" + } + }, + "contentName": "string.regexp.heredoc.php", + "end": "^(\\3)\\b", + "endCaptures": { + "0": { + "name": "punctuation.section.embedded.end.php" + }, + "1": { + "name": "keyword.operator.heredoc.php" + } + }, + "patterns": [ + { + "comment": "Escaped from the regexp – there can also be 2 backslashes (since 1 will escape the first)", + "match": "(\\\\){1,2}[.$^\\[\\]{}]", + "name": "constant.character.escape.regex.php" + }, + { + "captures": { + "1": { + "name": "punctuation.definition.arbitrary-repitition.php" + }, + "3": { + "name": "punctuation.definition.arbitrary-repitition.php" + } + }, + "match": "(\\{)\\d+(,\\d+)?(\\})", + "name": "string.regexp.arbitrary-repitition.php" + }, + { + "begin": "\\[(?:\\^?\\])?", + "captures": { + "0": { + "name": "punctuation.definition.character-class.php" + } + }, + "end": "\\]", + "name": "string.regexp.character-class.php", + "patterns": [ + { + "match": "\\\\[\\\\'\\[\\]]", + "name": "constant.character.escape.php" + } + ] + }, + { + "match": "[$^+*]", + "name": "keyword.operator.regexp.php" + }, + { + "begin": "(?<=^|\\s)(#)\\s(?=[[a-zA-Z0-9,. \\t?!-][^\\x{00}-\\x{7F}]]*$)", + "beginCaptures": { + "1": { + "name": "punctuation.definition.comment.php" + } + }, + "comment": "We are restrictive in what we allow to go after the comment character to avoid false positives, since the availability of comments depend on regexp flags.", + "end": "$\\n?", + "endCaptures": { + "0": { + "name": "punctuation.definition.comment.php" + } + }, + "name": "comment.line.number-sign.php" + } + ] + }, + { + "begin": "(<<<)\\s*(['\"]?)([a-zA-Z_]+[a-zA-Z0-9_]*)(\\2)", + "beginCaptures": { + "1": { + "name": "punctuation.definition.string.php" + }, + "3": { + "name": "keyword.operator.heredoc.php" + } + }, + "end": "^(\\3)\\b", + "endCaptures": { + "1": { + "name": "keyword.operator.heredoc.php" + } + } + } + ] + } + } + }, + "instantiation": { + "begin": "(?i)(new)\\s+", + "beginCaptures": { + "1": { + "name": "keyword.other.new.php" + } + }, + "end": "(?i)(?=[^$a-z0-9_\\\\])", + "patterns": [ + { + "match": "(parent|static|self)(?=[^a-z0-9_])", + "name": "storage.type.php" + }, + { + "include": "#class-name" + }, + { + "include": "#variable-name" + } + ] + }, + "interpolation": { + "comment": "http://www.php.net/manual/en/language.types.string.php#language.types.string.parsing", + "patterns": [ + { + "match": "\\\\[0-7]{1,3}", + "name": "constant.numeric.octal.php" + }, + { + "match": "\\\\x[0-9A-Fa-f]{1,2}", + "name": "constant.numeric.hex.php" + }, + { + "match": "\\\\[enrt\\\\\\$\\\"]", + "name": "constant.character.escape.php" + }, + { + "begin": "(\\{)(?=\\$.*?\\})", + "beginCaptures": { + "1": { + "name": "punctuation.definition.variable.php" + } + }, + "end": "(\\})", + "endCaptures": { + "1": { + "name": "punctuation.definition.variable.php" + } + }, + "patterns": [ + { + "include": "#language" + } + ] + }, + { + "include": "#variable-name" + } + ] + }, + "invoke-call": { + "captures": { + "1": { + "name": "punctuation.definition.variable.php" + }, + "2": { + "name": "variable.other.php" + } + }, + "match": "(?i)(\\$+)([a-z_][a-z_0-9]*)(?=\\s*\\()", + "name": "meta.function-call.invoke.php" + }, + "language": { + "patterns": [ + { + "include": "#comments" + }, + { + "match": "\\{", + "name": "punctuation.section.scope.begin.php" + }, + { + "match": "\\}", + "name": "punctuation.section.scope.end.php" + }, + { + "begin": "(?i)^\\s*(interface)\\s+([a-z0-9_]+)\\s*(extends)?\\s*", + "beginCaptures": { + "1": { + "name": "storage.type.interface.php" + }, + "2": { + "name": "entity.name.type.interface.php" + }, + "3": { + "name": "storage.modifier.extends.php" + } + }, + "end": "((?:[a-zA-Z0-9_]+\\s*,\\s*)*)([a-zA-Z0-9_]+)?\\s*(?:(?=\\{)|$)", + "endCaptures": { + "1": { + "patterns": [ + { + "match": "[a-zA-Z0-9_]+", + "name": "entity.other.inherited-class.php" + }, + { + "match": ",", + "name": "punctuation.separator.classes.php" + } + ] + }, + "2": { + "name": "entity.other.inherited-class.php" + } + }, + "name": "meta.interface.php", + "patterns": [ + { + "include": "#namespace" + } + ] + }, + { + "begin": "(?i)^\\s*(trait)\\s+([a-z0-9_]+)", + "beginCaptures": { + "1": { + "name": "storage.type.trait.php" + }, + "2": { + "name": "entity.name.type.trait.php" + } + }, + "end": "(?=[{])", + "name": "meta.trait.php", + "patterns": [ + { + "include": "#comments" + } + ] + }, + { + "begin": "(?i)(?:^|(?<=<\\?php))\\s*(namespace)\\b\\s+(?=([a-z0-9_\\\\]+\\s*($|[;{]|(\\/[\\/*])))|$)", + "beginCaptures": { + "1": { + "name": "keyword.other.namespace.php" + } + }, + "contentName": "entity.name.type.namespace.php", + "end": "(?i)(?=\\s*$|[^a-z0-9_\\\\])", + "name": "meta.namespace.php", + "patterns": [ + { + "match": "\\\\", + "name": "punctuation.separator.inheritance.php" + } + ] + }, + { + "begin": "(?i)\\s*\\b(use)\\s+(?:((const)|(function))\\s+)?", + "beginCaptures": { + "1": { + "name": "keyword.other.use.php" + }, + "3": { + "name": "storage.type.const.php" + }, + "4": { + "name": "storage.type.function.php" + } + }, + "end": "(?=;|(?:^\\s*$))", + "name": "meta.use.php", + "patterns": [ + { + "include": "#comments" + }, + { + "begin": "(?i)\\s*(?=[a-z_0-9\\\\])", + "end": "(?xi)(?:\n \t\t\t (?:\\s*(as)\\b\\s*([a-z_0-9]*)\\s*(?=,|;|$))\n \t\t\t |(?=,|;|$)\n \t\t\t )", + "endCaptures": { + "1": { + "name": "keyword.other.use-as.php" + }, + "2": { + "name": "support.other.namespace.use-as.php" + } + }, + "patterns": [ + { + "include": "#class-builtin" + }, + { + "begin": "(?i)\\s*(?=[\\\\a-z_0-9])", + "end": "$|(?=[\\s,;])", + "name": "support.other.namespace.use.php", + "patterns": [ + { + "match": "\\\\", + "name": "punctuation.separator.inheritance.php" + } + ] + } + ] + }, + { + "match": "\\s*,\\s*" + } + ] + }, + { + "begin": "(?i)^\\s*(abstract|final)?\\s*(class)\\s+([a-z0-9_]+)\\s*", + "beginCaptures": { + "1": { + "name": "storage.modifier.abstract.php" + }, + "2": { + "name": "storage.type.class.php" + }, + "3": { + "name": "entity.name.type.class.php" + } + }, + "end": "(?=[;{])", + "name": "meta.class.php", + "patterns": [ + { + "include": "#comments" + }, + { + "begin": "(?i)(extends)\\s+", + "beginCaptures": { + "1": { + "name": "storage.modifier.extends.php" + } + }, + "contentName": "meta.other.inherited-class.php", + "end": "(?i)(?=[^a-z_0-9\\\\])", + "patterns": [ + { + "begin": "(?i)(?=\\\\?[a-z_0-9]+\\\\)", + "end": "(?i)([a-z_][a-z_0-9]*)?(?=[^a-z0-9_\\\\])", + "endCaptures": { + "1": { + "name": "entity.other.inherited-class.php" + } + }, + "patterns": [ + { + "include": "#namespace" + } + ] + }, + { + "include": "#class-builtin" + }, + { + "include": "#namespace" + }, + { + "match": "(?i)[a-z_][a-z_0-9]*", + "name": "entity.other.inherited-class.php" + } + ] + }, + { + "begin": "(?i)(implements)\\s+", + "beginCaptures": { + "1": { + "name": "storage.modifier.implements.php" + } + }, + "end": "(?i)(?=[;{])", + "patterns": [ + { + "include": "#comments" + }, + { + "begin": "(?i)(?=[a-z0-9_\\\\]+)", + "contentName": "meta.other.inherited-class.php", + "end": "(?i)(?:\\s*(?:,|(?=[^a-z0-9_\\\\\\s]))\\s*)", + "patterns": [ + { + "begin": "(?i)(?=\\\\?[a-z_0-9]+\\\\)", + "end": "(?i)([a-z_][a-z_0-9]*)?(?=[^a-z0-9_\\\\])", + "endCaptures": { + "1": { + "name": "entity.other.inherited-class.php" + } + }, + "patterns": [ + { + "include": "#namespace" + } + ] + }, + { + "include": "#class-builtin" + }, + { + "include": "#namespace" + }, + { + "match": "(?i)[a-z_][a-z_0-9]*", + "name": "entity.other.inherited-class.php" + } + ] + } + ] + } + ] + }, + { + "captures": { + "1": { + "name": "keyword.control.php" + } + }, + "match": "\\s*\\b((break|c(ase|ontinue)|d(e(clare|fault)|ie|o)|e(lse(if)?|nd(declare|for(each)?|if|switch|while)|xit)|for(each)?|if|return|switch|use|while|yield))\\b" + }, + { + "begin": "(?i)\\b((?:require|include)(?:_once)?)\\b\\s*", + "beginCaptures": { + "1": { + "name": "keyword.control.import.include.php" + } + }, + "end": "(?=\\s|;|$)", + "name": "meta.include.php", + "patterns": [ + { + "include": "#language" + } + ] + }, + { + "begin": "\\b(catch)\\b\\s*\\(\\s*", + "beginCaptures": { + "1": { + "name": "keyword.control.exception.catch.php" + } + }, + "end": "([A-Za-z_][A-Za-z_0-9]*)\\s*((\\$+)[a-zA-Z_\\x{7f}-\\x{ff}][a-zA-Z0-9_\\x{7f}-\\x{ff}]*)\\s*\\)", + "endCaptures": { + "1": { + "name": "support.class.exception.php" + }, + "2": { + "name": "variable.other.php" + }, + "3": { + "name": "punctuation.definition.variable.php" + } + }, + "name": "meta.catch.php", + "patterns": [ + { + "include": "#namespace" + } + ] + }, + { + "match": "\\b(catch|try|throw|exception|finally)\\b", + "name": "keyword.control.exception.php" + }, + { + "begin": "(?i)\\b(function)\\s*(&\\s*)?(?=\\()", + "beginCaptures": { + "1": { + "name": "storage.type.function.php" + }, + "2": { + "name": "storage.modifier.reference.php" + } + }, + "end": "(?=\\{)", + "name": "meta.function.closure.php", + "patterns": [ + { + "begin": "(\\()", + "beginCaptures": { + "1": { + "name": "punctuation.definition.parameters.begin.php" + } + }, + "contentName": "meta.function.arguments.php", + "end": "(\\))", + "endCaptures": { + "1": { + "name": "punctuation.definition.parameters.end.php" + } + }, + "patterns": [ + { + "include": "#function-arguments" + } + ] + }, + { + "begin": "(?i)(use)\\s*(\\()", + "beginCaptures": { + "1": { + "name": "keyword.other.function.use.php" + }, + "2": { + "name": "punctuation.definition.parameters.begin.php" + } + }, + "end": "(\\))", + "endCaptures": { + "1": { + "name": "punctuation.definition.parameters.end.php" + } + }, + "patterns": [ + { + "captures": { + "1": { + "name": "storage.modifier.reference.php" + }, + "2": { + "name": "variable.other.php" + }, + "3": { + "name": "punctuation.definition.variable.php" + } + }, + "match": "(?:\\s*(&))?\\s*((\\$+)[a-zA-Z_\\x{7f}-\\x{ff}][a-zA-Z0-9_\\x{7f}-\\x{ff}]*)\\s*(?=,|\\))", + "name": "meta.function.closure.use.php" + } + ] + } + ] + }, + { + "begin": "(?x)\\s*\n\t\t\t\t\t ((?:(?:final|abstract|public|private|protected|static)\\s+)*)\n\t\t\t\t (function)\n\t\t\t\t (?:\\s+|(\\s*&\\s*))\n\t\t\t\t (?:\n\t\t\t\t (__(?:call|construct|debugInfo|destruct|get|set|isset|unset|tostring|clone|set_state|sleep|wakeup|autoload|invoke|callStatic))\n\t\t\t\t |([a-zA-Z0-9_]+)\n\t\t\t\t )\n\t\t\t\t \\s*\n\t\t\t\t (\\()", + "beginCaptures": { + "1": { + "patterns": [ + { + "match": "final|abstract|public|private|protected|static", + "name": "storage.modifier.php" + } + ] + }, + "2": { + "name": "storage.type.function.php" + }, + "3": { + "name": "storage.modifier.reference.php" + }, + "4": { + "name": "support.function.magic.php" + }, + "5": { + "name": "entity.name.function.php" + }, + "6": { + "name": "punctuation.definition.parameters.begin.php" + } + }, + "contentName": "meta.function.arguments.php", + "end": "(\\))", + "endCaptures": { + "1": { + "name": "punctuation.definition.parameters.end.php" + } + }, + "name": "meta.function.php", + "patterns": [ + { + "include": "#function-arguments" + } + ] + }, + { + "include": "#invoke-call" + }, + { + "begin": "(?xi)\\s*(?=\n\t\t\t\t [a-z_0-9$\\\\]+(::)\n (?:\n \t\t\t\t ([a-z_][a-z_0-9]*)\\s*\\(\n \t\t\t\t |\n \t\t\t\t ((\\$+)[a-z_\\x{7f}-\\x{ff}][a-z0-9_\\x{7f}-\\x{ff}]*)\n \t\t\t\t |\n \t\t\t\t ([a-z_\\x{7f}-\\x{ff}][a-z0-9_\\x{7f}-\\x{ff}]*)\n \t\t\t\t)?\n\t\t\t\t )", + "end": "(?x)(::)\n (?:\n \t\t\t\t ([A-Za-z_][A-Za-z_0-9]*)\\s*\\(\n \t\t\t\t |\n \t\t\t\t ((\\$+)[a-zA-Z_\\x{7f}-\\x{ff}][a-zA-Z0-9_\\x{7f}-\\x{ff}]*)\n \t\t\t\t |\n \t\t\t\t ([a-zA-Z_\\x{7f}-\\x{ff}][a-zA-Z0-9_\\x{7f}-\\x{ff}]*)\n \t\t\t\t)?", + "endCaptures": { + "1": { + "name": "keyword.operator.class.php" + }, + "2": { + "name": "meta.function-call.static.php" + }, + "3": { + "name": "variable.other.class.php" + }, + "4": { + "name": "punctuation.definition.variable.php" + }, + "5": { + "name": "constant.other.class.php" + } + }, + "patterns": [ + { + "match": "(self|static|parent)\\b", + "name": "storage.type.php" + }, + { + "include": "#class-name" + }, + { + "include": "#variable-name" + } + ] + }, + { + "include": "#variables" + }, + { + "include": "#strings" + }, + { + "captures": { + "1": { + "name": "support.function.construct.php" + }, + "2": { + "name": "punctuation.definition.array.begin.php" + }, + "3": { + "name": "punctuation.definition.array.end.php" + } + }, + "match": "(array)(\\()(\\))", + "name": "meta.array.empty.php" + }, + { + "begin": "(array)(\\()", + "beginCaptures": { + "1": { + "name": "support.function.construct.php" + }, + "2": { + "name": "punctuation.definition.array.begin.php" + } + }, + "end": "\\)", + "endCaptures": { + "0": { + "name": "punctuation.definition.array.end.php" + } + }, + "name": "meta.array.php", + "patterns": [ + { + "include": "#language" + } + ] + }, + { + "captures": { + "1": { + "name": "storage.type.php" + } + }, + "match": "(?i)\\s*\\(\\s*(array|real|double|float|int(eger)?|bool(ean)?|string|object|binary|unset)\\s*\\)" + }, + { + "match": "(?i)\\b(array|real|double|float|int(eger)?|bool(ean)?|string|class|clone|var|function|interface|trait|parent|self|object)\\b", + "name": "storage.type.php" + }, + { + "match": "(?i)\\b(global|abstract|const|extends|implements|final|p(r(ivate|otected)|ublic)|static)\\b", + "name": "storage.modifier.php" + }, + { + "include": "#object" + }, + { + "match": ";", + "name": "punctuation.terminator.expression.php" + }, + { + "include": "#heredoc" + }, + { + "match": "\\.=?", + "name": "keyword.operator.string.php" + }, + { + "match": "=>", + "name": "keyword.operator.key.php" + }, + { + "captures": { + "1": { + "name": "keyword.operator.assignment.php" + }, + "2": { + "name": "storage.modifier.reference.php" + }, + "3": { + "name": "storage.modifier.reference.php" + } + }, + "match": "(?:(\\=)(&))|(&(?=[$A-Za-z_]))" + }, + { + "match": "(@)", + "name": "keyword.operator.error-control.php" + }, + { + "match": "(===|==|!==|!=|<>)", + "name": "keyword.operator.comparison.php" + }, + { + "match": "=|\\+=|\\-=|\\*=|/=|%=|&=|\\|=|\\^=|<<=|>>=", + "name": "keyword.operator.assignment.php" + }, + { + "match": "(<=|>=|<|>)", + "name": "keyword.operator.comparison.php" + }, + { + "match": "(\\-\\-|\\+\\+)", + "name": "keyword.operator.increment-decrement.php" + }, + { + "match": "(\\-|\\+|\\*|/|%)", + "name": "keyword.operator.arithmetic.php" + }, + { + "match": "(?i)(!|&&|\\|\\|)|\\b(and|or|xor|as)\\b", + "name": "keyword.operator.logical.php" + }, + { + "include": "#function-call" + }, + { + "match": "<<|>>|~|\\^|&|\\|", + "name": "keyword.operator.bitwise.php" + }, + { + "begin": "(?i)\\b(instanceof)\\b\\s+(?=[\\\\$a-z_])", + "beginCaptures": { + "1": { + "name": "keyword.operator.type.php" + } + }, + "end": "(?=[^\\\\$A-Za-z_0-9])", + "patterns": [ + { + "include": "#class-name" + }, + { + "include": "#variable-name" + } + ] + }, + { + "include": "#numbers" + }, + { + "include": "#instantiation" + }, + { + "captures": { + "1": { + "name": "keyword.control.goto.php" + }, + "2": { + "name": "support.other.php" + } + }, + "match": "(?i)(goto)\\s+([a-z_][a-z_0-9]*)" + }, + { + "captures": { + "1": { + "name": "entity.name.goto-label.php" + } + }, + "match": "(?i)^\\s*([a-z_][a-z_0-9]*)\\s*:" + }, + { + "include": "#string-backtick" + }, + { + "begin": "\\[", + "beginCaptures": { + "0": { + "name": "punctuation.section.array.begin.php" + } + }, + "end": "\\]", + "endCaptures": { + "0": { + "name": "punctuation.section.array.end.php" + } + }, + "patterns": [ + { + "include": "#language" + } + ] + }, + { + "include": "#constants" + } + ] + }, + "namespace": { + "begin": "(?i)(?:(namespace)|[a-z0-9_]+)?(\\\\)(?=.*?[^a-z_0-9\\\\])", + "beginCaptures": { + "1": { + "name": "variable.language.namespace.php" + }, + "2": { + "name": "punctuation.separator.inheritance.php" + } + }, + "end": "(?i)(?=[a-z0-9_]*[^a-z0-9_\\\\])", + "name": "support.other.namespace.php", + "patterns": [ + { + "captures": { + "1": { + "name": "punctuation.separator.inheritance.php" + } + }, + "match": "(?i)(\\\\)" + } + ] + }, + "numbers": { + "match": "\\b((0(x|X)[0-9a-fA-F]*)|(([0-9]+\\.?[0-9]*)|(\\.[0-9]+))((e|E)(\\+|-)?[0-9]+)?)\\b", + "name": "constant.numeric.php" + }, + "object": { + "patterns": [ + { + "begin": "(->)(\\$?\\{)", + "beginCaptures": { + "1": { + "name": "keyword.operator.class.php" + }, + "2": { + "name": "punctuation.definition.variable.php" + } + }, + "end": "(\\})", + "endCaptures": { + "1": { + "name": "punctuation.definition.variable.php" + } + }, + "patterns": [ + { + "include": "#language" + } + ] + }, + { + "captures": { + "1": { + "name": "keyword.operator.class.php" + }, + "2": { + "name": "meta.function-call.object.php" + }, + "3": { + "name": "variable.other.property.php" + }, + "4": { + "name": "punctuation.definition.variable.php" + } + }, + "match": "(?x)(->)\n \t\t\t\t(?:\n \t\t\t\t ([A-Za-z_][A-Za-z_0-9]*)\\s*\\(\n \t\t\t\t |\n \t\t\t\t ((\\$+)?[a-zA-Z_\\x{7f}-\\x{ff}][a-zA-Z0-9_\\x{7f}-\\x{ff}]*)\n \t\t\t\t)?" + } + ] + }, + "parameter-default-types": { + "patterns": [ + { + "include": "#strings" + }, + { + "include": "#numbers" + }, + { + "include": "#string-backtick" + }, + { + "include": "#variables" + }, + { + "match": "=>", + "name": "keyword.operator.key.php" + }, + { + "match": "=", + "name": "keyword.operator.assignment.php" + }, + { + "match": "&(?=\\s*\\$)", + "name": "storage.modifier.reference.php" + }, + { + "begin": "(array)\\s*(\\()", + "beginCaptures": { + "1": { + "name": "support.function.construct.php" + }, + "2": { + "name": "punctuation.definition.array.begin.php" + } + }, + "end": "\\)", + "endCaptures": { + "0": { + "name": "punctuation.definition.array.end.php" + } + }, + "name": "meta.array.php", + "patterns": [ + { + "include": "#parameter-default-types" + } + ] + }, + { + "include": "#instantiation" + }, + { + "begin": "(?xi)\\s*(?=\n\t\t\t\t [a-z_0-9\\\\]+(::)\n \t\t\t\t ([a-z_\\x{7f}-\\x{ff}][a-z0-9_\\x{7f}-\\x{ff}]*)?\n\t\t\t\t )", + "end": "(?i)(::)([a-z_\\x{7f}-\\x{ff}][a-z0-9_\\x{7f}-\\x{ff}]*)?", + "endCaptures": { + "1": { + "name": "keyword.operator.class.php" + }, + "2": { + "name": "constant.other.class.php" + } + }, + "patterns": [ + { + "include": "#class-name" + } + ] + }, + { + "include": "#constants" + } + ] + }, + "php_doc": { + "patterns": [ + { + "comment": "PHPDocumentor only recognises lines with an asterisk as the first non-whitespaces character", + "match": "^(?!\\s*\\*).*$\\n?", + "name": "invalid.illegal.missing-asterisk.phpdoc.php" + }, + { + "captures": { + "1": { + "name": "keyword.other.phpdoc.php" + }, + "3": { + "name": "storage.modifier.php" + }, + "4": { + "name": "invalid.illegal.wrong-access-type.phpdoc.php" + } + }, + "match": "^\\s*\\*\\s*(@access)\\s+((public|private|protected)|(.+))\\s*$" + }, + { + "captures": { + "1": { + "name": "keyword.other.phpdoc.php" + }, + "2": { + "name": "markup.underline.link.php" + } + }, + "match": "(@xlink)\\s+(.+)\\s*$" + }, + { + "match": "\\@(a(pi|bstract|uthor)|c(ategory|opyright)|example|global|internal|li(cense|nk)|method|p(roperty(\\-read|\\-write|)|ackage|aram)|return|s(ee|ince|ource|tatic|ubpackage)|t(hrows|odo)|v(ar|ersion)|uses|deprecated|final|ignore)\\b", + "name": "keyword.other.phpdoc.php" + }, + { + "captures": { + "1": { + "name": "keyword.other.phpdoc.php" + } + }, + "match": "\\{(@(link)).+?\\}", + "name": "meta.tag.inline.phpdoc.php" + } + ] + }, + "regex-double-quoted": { + "begin": "(?x)\"/ (?= (\\\\.|[^\"/])++/[imsxeADSUXu]*\" )", + "beginCaptures": { + "0": { + "name": "punctuation.definition.string.begin.php" + } + }, + "end": "(/)([imsxeADSUXu]*)(\")", + "endCaptures": { + "0": { + "name": "punctuation.definition.string.end.php" + } + }, + "name": "string.regexp.double-quoted.php", + "patterns": [ + { + "comment": "Escaped from the regexp – there can also be 2 backslashes (since 1 will escape the first)", + "match": "(\\\\){1,2}[.$^\\[\\]{}]", + "name": "constant.character.escape.regex.php" + }, + { + "include": "#interpolation" + }, + { + "captures": { + "1": { + "name": "punctuation.definition.arbitrary-repetition.php" + }, + "3": { + "name": "punctuation.definition.arbitrary-repetition.php" + } + }, + "match": "(\\{)\\d+(,\\d+)?(\\})", + "name": "string.regexp.arbitrary-repetition.php" + }, + { + "begin": "\\[(?:\\^?\\])?", + "captures": { + "0": { + "name": "punctuation.definition.character-class.php" + } + }, + "end": "\\]", + "name": "string.regexp.character-class.php", + "patterns": [ + { + "include": "#interpolation" + } + ] + }, + { + "match": "[$^+*]", + "name": "keyword.operator.regexp.php" + } + ] + }, + "regex-single-quoted": { + "begin": "(?x)'/ (?= ( \\\\ (?: \\\\ (?: \\\\ [\\\\']? | [^'] ) | . ) | [^'/] )++/[imsxeADSUXu]*' )", + "beginCaptures": { + "0": { + "name": "punctuation.definition.string.begin.php" + } + }, + "end": "(/)([imsxeADSUXu]*)(')", + "endCaptures": { + "0": { + "name": "punctuation.definition.string.end.php" + } + }, + "name": "string.regexp.single-quoted.php", + "patterns": [ + { + "captures": { + "1": { + "name": "punctuation.definition.arbitrary-repetition.php" + }, + "3": { + "name": "punctuation.definition.arbitrary-repetition.php" + } + }, + "match": "(\\{)\\d+(,\\d+)?(\\})", + "name": "string.regexp.arbitrary-repetition.php" + }, + { + "begin": "\\[(?:\\^?\\])?", + "captures": { + "0": { + "name": "punctuation.definition.character-class.php" + } + }, + "end": "\\]", + "name": "string.regexp.character-class.php", + "patterns": [ + { + "include": "#single_quote_regex_escape" + } + ] + }, + { + "match": "[$^+*]", + "name": "keyword.operator.regexp.php" + }, + { + "include": "#single_quote_regex_escape" + } + ], + "repository": { + "single_quote_regex_escape": { + "comment": "Support both PHP string and regex escaping", + "match": "(?x) \\\\ (?: \\\\ (?: \\\\ [\\\\']? | [^'] ) | . )", + "name": "constant.character.escape.php" + } + } + }, + "sql-string-double-quoted": { + "begin": "\"\\s*(?=(SELECT|INSERT|UPDATE|DELETE|CREATE|REPLACE|ALTER)\\b)", + "beginCaptures": { + "0": { + "name": "punctuation.definition.string.begin.php" + } + }, + "contentName": "source.sql.embedded.php", + "end": "\"", + "endCaptures": { + "0": { + "name": "punctuation.definition.string.end.php" + } + }, + "name": "string.quoted.double.sql.php", + "patterns": [ + { + "match": "#(\\\\\"|[^\"])*(?=\"|$\\n?)", + "name": "comment.line.number-sign.sql" + }, + { + "match": "--(\\\\\"|[^\"])*(?=\"|$\\n?)", + "name": "comment.line.double-dash.sql" + }, + { + "match": "\\\\[\\\\\"`']", + "name": "constant.character.escape.php" + }, + { + "comment": "Unclosed strings must be captured to avoid them eating the remainder of the PHP script\n\t\t\t\t\tSample case: $sql = \"SELECT * FROM bar WHERE foo = '\" . $variable . \"'\"", + "match": "'(?=((\\\\')|[^'\"])*(\"|$))", + "name": "string.quoted.single.unclosed.sql" + }, + { + "comment": "Unclosed strings must be captured to avoid them eating the remainder of the PHP script\n\t\t\t\t\tSample case: $sql = \"SELECT * FROM bar WHERE foo = '\" . $variable . \"'\"", + "match": "`(?=((\\\\`)|[^`\"])*(\"|$))", + "name": "string.quoted.other.backtick.unclosed.sql" + }, + { + "begin": "'", + "end": "'", + "name": "string.quoted.single.sql", + "patterns": [ + { + "include": "#interpolation" + } + ] + }, + { + "begin": "`", + "end": "`", + "name": "string.quoted.other.backtick.sql", + "patterns": [ + { + "include": "#interpolation" + } + ] + }, + { + "include": "#interpolation" + }, + { + "include": "source.sql" + } + ] + }, + "sql-string-single-quoted": { + "begin": "'\\s*(?=(SELECT|INSERT|UPDATE|DELETE|CREATE|REPLACE|ALTER)\\b)", + "beginCaptures": { + "0": { + "name": "punctuation.definition.string.begin.php" + } + }, + "contentName": "source.sql.embedded.php", + "end": "'", + "endCaptures": { + "0": { + "name": "punctuation.definition.string.end.php" + } + }, + "name": "string.quoted.single.sql.php", + "patterns": [ + { + "match": "#(\\\\'|[^'])*(?='|$\\n?)", + "name": "comment.line.number-sign.sql" + }, + { + "match": "--(\\\\'|[^'])*(?='|$\\n?)", + "name": "comment.line.double-dash.sql" + }, + { + "match": "\\\\[\\\\'`\"]", + "name": "constant.character.escape.php" + }, + { + "comment": "Unclosed strings must be captured to avoid them eating the remainder of the PHP script\n\t\t\t\t\tSample case: $sql = \"SELECT * FROM bar WHERE foo = '\" . $variable . \"'\"", + "match": "`(?=((\\\\`)|[^`'])*('|$))", + "name": "string.quoted.other.backtick.unclosed.sql" + }, + { + "comment": "Unclosed strings must be captured to avoid them eating the remainder of the PHP script\n\t\t\t\t\tSample case: $sql = \"SELECT * FROM bar WHERE foo = '\" . $variable . \"'\"", + "match": "\"(?=((\\\\\")|[^\"'])*('|$))", + "name": "string.quoted.double.unclosed.sql" + }, + { + "include": "source.sql" + } + ] + }, + "string-backtick": { + "begin": "`", + "beginCaptures": { + "0": { + "name": "punctuation.definition.string.begin.php" + } + }, + "end": "`", + "endCaptures": { + "0": { + "name": "punctuation.definition.string.end.php" + } + }, + "name": "string.interpolated.php", + "patterns": [ + { + "match": "\\\\.", + "name": "constant.character.escape.php" + }, + { + "include": "#interpolation" + } + ] + }, + "string-double-quoted": { + "begin": "\"", + "beginCaptures": { + "0": { + "name": "punctuation.definition.string.begin.php" + } + }, + "comment": "This contentName is just to allow the usage of “select scope” to select the string contents first, then the string with quotes", + "contentName": "meta.string-contents.quoted.double.php", + "end": "\"", + "endCaptures": { + "0": { + "name": "punctuation.definition.string.end.php" + } + }, + "name": "string.quoted.double.php", + "patterns": [ + { + "include": "#interpolation" + } + ] + }, + "string-single-quoted": { + "begin": "'", + "beginCaptures": { + "0": { + "name": "punctuation.definition.string.begin.php" + } + }, + "contentName": "meta.string-contents.quoted.single.php", + "end": "'", + "endCaptures": { + "0": { + "name": "punctuation.definition.string.end.php" + } + }, + "name": "string.quoted.single.php", + "patterns": [ + { + "match": "\\\\[\\\\']", + "name": "constant.character.escape.php" + } + ] + }, + "strings": { + "patterns": [ + { + "include": "#regex-double-quoted" + }, + { + "include": "#sql-string-double-quoted" + }, + { + "include": "#string-double-quoted" + }, + { + "include": "#regex-single-quoted" + }, + { + "include": "#sql-string-single-quoted" + }, + { + "include": "#string-single-quoted" + } + ] + }, + "support": { + "patterns": [ + { + "match": "(?i)\\bapc_(s(tore|ma_info)|c(ompile_file|lear_cache|a(s|che_info))|inc|de(c|fine_constants|lete(_file)?)|exists|fetch|load_constants|add|bin_(dump(file)?|load(file)?))\\b", + "name": "support.function.apc.php" + }, + { + "match": "(?i)\\b(s(huffle|izeof|ort)|n(ext|at(sort|casesort))|c(o(unt|mpact)|urrent)|in_array|u(sort|ksort|asort)|p(os|rev)|e(nd|ach|xtract)|k(sort|ey(_exists)?|rsort)|list|a(sort|r(sort|ray(_(s(hift|um|plice|earch|lice)|c(h(unk|ange_key_case)|o(unt_values|lumn|mbine))|intersect(_(u(key|assoc)|key|assoc))?|diff(_(u(key|assoc)|key|assoc))?|u(n(shift|ique)|intersect(_(uassoc|assoc))?|diff(_(uassoc|assoc))?)|p(op|ush|ad|roduct)|values|key(s|_exists)|f(il(ter|l(_keys)?)|lip)|walk(_recursive)?|r(e(duce|place(_recursive)?|verse)|and)|m(ultisort|erge(_recursive)?|ap)))?))|r(sort|eset|ange))\\b", + "name": "support.function.array.php" + }, + { + "match": "(?i)\\b(s(how_source|ys_getloadavg|leep)|highlight_(string|file)|con(stant|nection_(status|aborted))|time_(sleep_until|nanosleep)|ignore_user_abort|d(ie|efine(d)?)|u(sleep|n(iqid|pack))|__halt_compiler|p(hp_(strip_whitespace|check_syntax)|ack)|e(val|xit)|get_browser)\\b", + "name": "support.function.basic_functions.php" + }, + { + "match": "(?i)\\bbc(s(cale|ub|qrt)|comp|div|pow(mod)?|add|m(od|ul))\\b", + "name": "support.function.bcmath.php" + }, + { + "match": "(?i)\\bblenc_encrypt\\b", + "name": "support.function.blenc.php" + }, + { + "match": "(?i)\\bbz(c(ompress|lose)|open|decompress|err(str|no|or)|flush|write|read)\\b", + "name": "support.function.bz2.php" + }, + { + "match": "(?i)\\b(GregorianToJD|cal_(to_jd|info|days_in_month|from_jd)|unixtojd|jdto(unix|jewish)|easter_da(ys|te)|J(ulianToJD|ewishToJD|D(MonthName|To(Gregorian|Julian|French)|DayOfWeek))|FrenchToJD)\\b", + "name": "support.function.calendar.php" + }, + { + "match": "(?i)\\b(c(lass_(exists|alias)|all_user_method(_array)?)|trait_exists|i(s_(subclass_of|a)|nterface_exists)|__autoload|property_exists|get_(c(lass(_(vars|methods))?|alled_class)|object_vars|declared_(classes|traits|interfaces)|parent_class)|method_exists)\\b", + "name": "support.function.classobj.php" + }, + { + "match": "(?i)\\b(com_(create_guid|print_typeinfo|event_sink|load_typelib|get_active_object|message_pump)|variant_(s(ub|et(_type)?)|n(ot|eg)|c(a(st|t)|mp)|i(nt|div|mp)|or|d(iv|ate_(to_timestamp|from_timestamp))|pow|eqv|fix|a(nd|dd|bs)|round|get_type|xor|m(od|ul)))\\b", + "name": "support.function.com.php" + }, + { + "match": "(?i)\\bctype_(space|cntrl|digit|upper|p(unct|rint)|lower|al(num|pha)|graph|xdigit)\\b", + "name": "support.function.ctype.php" + }, + { + "match": "(?i)\\bcurl_(s(hare_(setopt|close|init)|trerror|etopt(_array)?)|c(opy_handle|lose)|init|unescape|pause|e(scape|rr(no|or)|xec)|version|file_create|reset|getinfo|multi_(s(trerror|e(topt|lect))|close|in(it|fo_read)|exec|add_handle|remove_handle|getcontent))\\b", + "name": "support.function.curl.php" + }, + { + "match": "(?i)\\b(str(totime|ptime|ftime)|checkdate|time(zone_(name_(from_abbr|get)|transitions_get|identifiers_list|o(pen|ffset_get)|version_get|location_get|abbreviations_list))?|idate|date(_(su(n(set|_info|rise)|b)|create(_(immutable(_from_format)?|from_format))?|time(stamp_(set|get)|zone_(set|get)|_set)|i(sodate_set|nterval_(create_from_date_string|format))|offset_get|d(iff|efault_timezone_(set|get)|ate_set)|parse(_from_format)?|format|add|get_last_errors|modify))?|localtime|g(et(timeofday|date)|m(strftime|date|mktime))|m(icrotime|ktime))\\b", + "name": "support.function.datetime.php" + }, + { + "match": "(?i)\\bdba_(sync|handlers|nextkey|close|insert|op(timize|en)|delete|popen|exists|key_split|f(irstkey|etch)|list|replace)\\b", + "name": "support.function.dba.php" + }, + { + "match": "(?i)\\bdbx_(sort|c(o(nnect|mpare)|lose)|e(scape_string|rror)|query|fetch_row)\\b", + "name": "support.function.dbx.php" + }, + { + "match": "(?i)\\b(scandir|c(h(dir|root)|losedir)|opendir|dir|re(winddir|addir)|getcwd)\\b", + "name": "support.function.dir.php" + }, + { + "match": "(?i)\\beio_(s(y(nc(_file_range|fs)?|mlink)|tat(vfs)?|e(ndfile|t_m(in_parallel|ax_(idle|p(oll_(time|reqs)|arallel)))|ek))|n(threads|op|pending|re(qs|ady))|c(h(own|mod)|ustom|lose|ancel)|truncate|init|open|dup2|u(nlink|time)|poll|event_loop|f(s(ync|tat(vfs)?)|ch(own|mod)|truncate|datasync|utime|allocate)|write|l(stat|ink)|r(e(name|a(d(dir|link|ahead)?|lpath))|mdir)|g(et_(event_stream|last_error)|rp(_(cancel|limit|add))?)|mk(nod|dir)|busy)\\b", + "name": "support.function.eio.php" + }, + { + "match": "(?i)\\benchant_(dict_(s(tore_replacement|uggest)|check|is_in_session|describe|quick_check|add_to_(session|personal)|get_error)|broker_(set_ordering|init|d(ict_exists|escribe)|free(_dict)?|list_dicts|request_(dict|pwl_dict)|get_error))\\b", + "name": "support.function.enchant.php" + }, + { + "match": "(?i)\\b(s(plit(i)?|ql_regcase)|ereg(i(_replace)?|_replace)?)\\b", + "name": "support.function.ereg.php" + }, + { + "match": "(?i)\\b(set_e(rror_handler|xception_handler)|trigger_error|debug_(print_backtrace|backtrace)|user_error|error_(log|reporting|get_last)|restore_e(rror_handler|xception_handler))\\b", + "name": "support.function.errorfunc.php" + }, + { + "match": "(?i)\\b(s(hell_exec|ystem)|p(assthru|roc_(nice|close|terminate|open|get_status))|e(scapeshell(cmd|arg)|xec))\\b", + "name": "support.function.exec.php" + }, + { + "match": "(?i)\\b(exif_(t(humbnail|agname)|imagetype|read_data)|read_exif_data)\\b", + "name": "support.function.exif.php" + }, + { + "match": "(?i)\\bfann_(s(huffle_train_data|cale_(train(_data)?|input(_train_data)?|output(_train_data)?)|ubset_train_data|et_(s(caling_params|arprop_(step_error_(shift|threshold_factor)|temperature|weight_decay_shift))|ca(scade_(num_candidate_groups|candidate_(stagnation_epochs|change_fraction|limit)|output_(stagnation_epochs|change_fraction)|weight_multiplier|activation_(steepnesses|functions)|m(in_(cand_epochs|out_epochs)|ax_(cand_epochs|out_epochs)))|llback)|train(ing_algorithm|_(stop_function|error_function))|input_scaling_params|output_scaling_params|error_log|quickprop_(decay|mu)|weight(_array)?|learning_(rate|momentum)|activation_(steepness(_(hidden|output|layer))?|function(_(hidden|output|layer))?)|rprop_(increase_factor|de(crease_factor|lta_(zero|m(in|ax))))|bit_fail_limit)|ave(_train)?)|num_(input_train_data|output_train_data)|c(opy|lear_scaling_params|ascadetrain_on_(data|file)|reate_(s(hortcut(_array)?|tandard(_array)?|parse(_array)?)|train(_from_callback)?|from_file))|t(est(_data)?|rain(_(on_(data|file)|epoch))?)|init_weights|d(uplicate_train_data|es(cale_(train|input|output)|troy(_train)?))|print_error|length_train_data|r(un|e(set_(MSE|err(str|no))|ad_train_from_file)|andomize_weights)|get_(sarprop_(step_error_(shift|threshold_factor)|temperature|weight_decay_shift)|n(um_(input|output|layers)|etwork_type)|MSE|c(onnection_(array|rate)|ascade_(num_candidate(s|_groups)|candidate_(stagnation_epochs|change_fraction|limit)|output_(stagnation_epochs|change_fraction)|weight_multiplier|activation_(steepnesses(_count)?|functions(_count)?)|m(in_(cand_epochs|out_epochs)|ax_(cand_epochs|out_epochs))))|t(otal_(neurons|connections)|rain(ing_algorithm|_(stop_function|error_function)))|err(str|no)|quickprop_(decay|mu)|l(earning_(rate|momentum)|ayer_array)|activation_(steepness|function)|rprop_(increase_factor|de(crease_factor|lta_(zero|m(in|ax))))|bi(t_fail(_limit)?|as_array))|merge_train_data)\\b", + "name": "support.function.fann.php" + }, + { + "match": "(?i)\\b(s(ymlink|tat|et_file_buffer)|c(h(own|grp|mod)|opy|learstatcache)|t(ouch|empnam|mpfile)|is_(dir|uploaded_file|executable|file|writ(eable|able)|link|readable)|d(i(sk(_(total_space|free_space)|freespace)|rname)|elete)|u(nlink|mask)|p(close|open|a(thinfo|rse_ini_(string|file)))|f(s(canf|tat|eek)|nmatch|close|t(ell|runcate)|ile(size|ctime|type|inode|owner|_(put_contents|exists|get_contents)|perms|atime|group|mtime)?|open|p(ut(s|csv)|assthru)|eof|flush|write|lock|read|get(s(s)?|c(sv)?))|l(stat|ch(own|grp)|ink(info)?)|r(e(name|wind|a(d(file|link)|lpath(_cache_(size|get))?))|mdir)|glob|m(ove_uploaded_file|kdir)|basename)\\b", + "name": "support.function.file.php" + }, + { + "match": "(?i)\\b(finfo_(set_flags|close|open|file|buffer)|mime_content_type)\\b", + "name": "support.function.fileinfo.php" + }, + { + "match": "(?i)\\bfilter_(has_var|i(nput(_array)?|d)|var(_array)?|list)\\b", + "name": "support.function.filter.php" + }, + { + "match": "(?i)\\bfastcgi_finish_request\\b", + "name": "support.function.fpm.php" + }, + { + "match": "(?i)\\b(c(all_user_func(_array)?|reate_function)|unregister_tick_function|f(orward_static_call(_array)?|unc(tion_exists|_(num_args|get_arg(s)?)))|register_(shutdown_function|tick_function)|get_defined_functions)\\b", + "name": "support.function.funchand.php" + }, + { + "match": "(?i)\\b(ngettext|textdomain|d(ngettext|c(ngettext|gettext)|gettext)|gettext|bind(textdomain|_textdomain_codeset))\\b", + "name": "support.function.gettext.php" + }, + { + "match": "(?i)\\bgmp_(s(can(1|0)|trval|ign|ub|etbit|qrt(rem)?)|hamdist|ne(g|xtprime)|c(om|lrbit|mp)|testbit|i(n(tval|it|vert)|mport)|or|div(_(q(r)?|r)|exact)?|jacobi|p(o(pcount|w(m)?)|erfect_square|rob_prime)|export|fact|legendre|a(nd|dd|bs)|r(oot(rem)?|andom(_(range|bits))?)|gcd(ext)?|xor|m(od|ul))\\b", + "name": "support.function.gmp.php" + }, + { + "match": "(?i)\\bhash(_(hmac(_file)?|copy|init|update(_(stream|file))?|pbkdf2|equals|fi(nal|le)|algos))?\\b", + "name": "support.function.hash.php" + }, + { + "match": "(?i)\\b(http_(s(upport|end_(st(atus|ream)|content_(type|disposition)|data|file|last_modified))|head|negotiate_(c(harset|ontent_type)|language)|c(hunked_decode|ache_(etag|last_modified))|throttle|inflate|d(eflate|ate)|p(ost_(data|fields)|ut_(stream|data|file)|ersistent_handles_(c(ount|lean)|ident)|arse_(headers|cookie|params|message))|re(direct|quest(_(method_(name|unregister|exists|register)|body_encode))?)|get(_request_(headers|body(_stream)?))?|match_(etag|request_header|modified)|build_(str|cookie|url))|ob_(inflatehandler|deflatehandler|etaghandler))\\b", + "name": "support.function.http.php" + }, + { + "match": "(?i)\\b(iconv(_(s(tr(pos|len|rpos)|ubstr|et_encoding)|get_encoding|mime_(decode(_headers)?|encode)))?|ob_iconv_handler)\\b", + "name": "support.function.iconv.php" + }, + { + "match": "(?i)\\biis_(s(t(op_serv(ice|er)|art_serv(ice|er))|et_(s(cript_map|erver_rights)|dir_security|app_settings))|add_server|remove_server|get_(s(cript_map|erv(ice_state|er_(rights|by_(comment|path))))|dir_security))\\b", + "name": "support.function.iisfunc.php" + }, + { + "match": "(?i)\\b(i(ptc(parse|embed)|mage(s(y|cale|tring(up)?|et(style|t(hickness|ile)|interpolation|pixel|brush)|avealpha|x)|c(har(up)?|o(nvolution|py(res(ized|ampled)|merge(gray)?)?|lor(s(total|et|forindex)|closest(hwb|alpha)?|transparent|deallocate|exact(alpha)?|a(t|llocate(alpha)?)|resolve(alpha)?|match))|r(op(auto)?|eate(truecolor|from(string|jpeg|png|w(ebp|bmp)|g(if|d(2(part)?)?)|x(pm|bm)))?))|t(ypes|tf(text|bbox)|ruecolortopalette)|i(struecolor|nterlace)|2wbmp|d(estroy|ashedline)|jpeg|_type_to_(extension|mime_type)|p(s(slantfont|text|e(ncodefont|xtendfont)|freefont|loadfont|bbox)|ng|olygon|alette(copy|totruecolor))|ellipse|f(t(text|bbox)|il(ter|l(toborder|ed(polygon|ellipse|arc|rectangle))?)|ont(height|width)|lip)|w(ebp|bmp)|l(ine|oadfont|ayereffect)|a(ntialias|ffine(matrix(concat|get))?|lphablending|rc)|r(otate|ectangle)|g(if|d(2)?|ammacorrect|rab(screen|window))|xbm))|jpeg2wbmp|png2wbmp|g(d_info|etimagesize(fromstring)?))\\b", + "name": "support.function.image.php" + }, + { + "match": "(?i)\\b(s(ys_get_temp_dir|et_(time_limit|include_path|magic_quotes_runtime))|cli_(set_process_title|get_process_title)|ini_(set|alter|restore|get(_all)?)|zend_(thread_id|version|logo_guid)|dl|p(hp(credits|info|_(sapi_name|ini_(scanned_files|loaded_file)|uname|logo_guid)|version)|utenv)|extension_loaded|version_compare|assert(_options)?|restore_include_path|g(c_(collect_cycles|disable|enable(d)?)|et(opt|_(c(urrent_user|fg_var)|include(d_files|_path)|defined_constants|extension_funcs|loaded_extensions|required_files|magic_quotes_(runtime|gpc))|env|lastmod|rusage|my(inode|uid|pid|gid)))|m(emory_get_(usage|peak_usage)|a(in|gic_quotes_runtime)))\\b", + "name": "support.function.info.php" + }, + { + "match": "(?i)\\bibase_(se(t_event_handler|rv(ice_(detach|attach)|er_info))|n(um_(params|fields)|ame_result)|c(o(nnect|mmit(_ret)?)|lose)|trans|d(elete_user|rop_db|b_info)|p(connect|aram_info|repare)|e(rr(code|msg)|xecute)|query|f(ield_info|etch_(object|assoc|row)|ree_(event_handler|query|result))|wait_event|a(dd_user|ffected_rows)|r(ollback(_ret)?|estore)|gen_id|m(odify_user|aintain_db)|b(lob_(c(lose|ancel|reate)|i(nfo|mport)|open|echo|add|get)|ackup))\\b", + "name": "support.function.interbase.php" + }, + { + "match": "(?i)\\b(n(ormalizer_(normalize|is_normalized)|umfmt_(set_(symbol|text_attribute|pattern|attribute)|create|parse(_currency)?|format(_currency)?|get_(symbol|text_attribute|pattern|error_(code|message)|locale|attribute)))|collator_(s(ort(_with_sort_keys)?|et_(strength|attribute))|c(ompare|reate)|asort|get_(s(trength|ort_key)|error_(code|message)|locale|attribute))|transliterator_(create(_(inverse|from_rules))?|transliterate|list_ids|get_error_(code|message))|i(ntl(cal_get_error_(code|message)|tz_get_error_(code|message)|_(is_failure|error_name|get_error_(code|message)))|dn_to_(u(nicode|tf8)|ascii))|datefmt_(set_(calendar|timezone(_id)?|pattern|lenient)|create|is_lenient|parse|format(_object)?|localtime|get_(calendar(_object)?|time(type|zone(_id)?)|datetype|pattern|error_(code|message)|locale))|locale_(set_default|c(ompose|anonicalize)|parse|filter_matches|lookup|accept_from_http|get_(script|d(isplay_(script|name|variant|language|region)|efault)|primary_language|keywords|all_variants|region))|resourcebundle_(c(ount|reate)|locales|get(_error_(code|message))?)|grapheme_(s(tr(str|i(str|pos)|pos|len|r(ipos|pos))|ubstr)|extract)|msgfmt_(set_pattern|create|parse(_message)?|format(_message)?|get_(pattern|error_(code|message)|locale)))\\b", + "name": "support.function.intl.php" + }, + { + "match": "(?i)\\bjson_(decode|encode|last_error(_msg)?)\\b", + "name": "support.function.json.php" + }, + { + "match": "(?i)\\bldap_(s(tart_tls|ort|e(t_(option|rebind_proc)|arch)|asl_bind)|next_(entry|attribute|reference)|c(o(n(nect|trol_paged_result(_response)?)|unt_entries|mpare)|lose)|t61_to_8859|d(n2ufn|elete)|8859_to_t61|unbind|parse_re(sult|ference)|e(scape|rr(no|2str|or)|xplode_dn)|f(irst_(entry|attribute|reference)|ree_result)|list|add|re(name|ad)|get_(option|dn|entries|values(_len)?|attributes)|mod(ify(_batch)?|_(del|add|replace))|bind)\\b", + "name": "support.function.ldap.php" + }, + { + "match": "(?i)\\blibxml_(set_(streams_context|external_entity_loader)|clear_errors|disable_entity_loader|use_internal_errors|get_(errors|last_error))\\b", + "name": "support.function.libxml.php" + }, + { + "match": "(?i)\\b(ezmlm_hash|mail)\\b", + "name": "support.function.mail.php" + }, + { + "match": "(?i)\\b(s(in(h)?|qrt|rand)|h(ypot|exdec)|c(os(h)?|eil)|tan(h)?|is_(nan|infinite|finite)|octdec|de(c(hex|oct|bin)|g2rad)|p(i|ow)|exp(m1)?|f(loor|mod)|l(cg_value|og(1(p|0))?)|a(sin(h)?|cos(h)?|tan(h|2)?|bs)|r(ound|a(nd|d2deg))|getrandmax|m(t_(srand|rand|getrandmax)|in|ax)|b(indec|ase_convert))\\b", + "name": "support.function.math.php" + }, + { + "match": "(?i)\\bmb_(s(tr(str|cut|to(upper|lower)|i(str|pos|mwidth)|pos|width|len|r(chr|i(chr|pos)|pos))|ubst(itute_character|r(_count)?)|plit|end_mail)|http_(input|output)|c(heck_encoding|onvert_(case|encoding|variables|kana))|internal_encoding|output_handler|de(code_(numericentity|mimeheader)|tect_(order|encoding))|p(arse_str|referred_mime_name)|e(ncod(ing_aliases|e_(numericentity|mimeheader))|reg(i(_replace)?|_(search(_(setpos|init|pos|regs|get(pos|regs)))?|replace(_callback)?|match))?)|l(ist_encodings|anguage)|regex_(set_options|encoding)|get_info)\\b", + "name": "support.function.mbstring.php" + }, + { + "match": "(?i)\\bm(crypt_(c(fb|reate_iv|bc)|ofb|decrypt|e(nc(_(self_test|is_block_(algorithm(_mode)?|mode)|get_(supported_key_sizes|iv_size|key_size|algorithms_name|modes_name|block_size))|rypt)|cb)|list_(algorithms|modes)|ge(neric(_(init|deinit|end))?|t_(cipher_name|iv_size|key_size|block_size))|module_(self_test|close|is_block_(algorithm(_mode)?|mode)|open|get_(supported_key_sizes|algo_(key_size|block_size))))|decrypt_generic)\\b", + "name": "support.function.mcrypt.php" + }, + { + "match": "(?i)\\bmemcache_debug\\b", + "name": "support.function.memcache.php" + }, + { + "match": "(?i)\\bmhash(_(count|keygen_s2k|get_(hash_name|block_size)))?\\b", + "name": "support.function.mhash.php" + }, + { + "match": "(?i)\\b(log_(cmd_(insert|delete|update)|killcursor|write_batch|reply|getmore)|bson_(decode|encode))\\b", + "name": "support.function.mongo.php" + }, + { + "match": "(?i)\\bmysql_(s(tat|e(t_charset|lect_db))|num_(fields|rows)|c(onnect|l(ient_encoding|ose)|reate_db)|t(hread_id|ablename)|in(sert_id|fo)|d(ata_seek|rop_db|b_(name|query))|unbuffered_query|p(connect|ing)|e(scape_string|rr(no|or))|query|f(ield_(seek|name|t(ype|able)|flags|len)|etch_(object|field|lengths|a(ssoc|rray)|row)|ree_result)|list_(tables|dbs|processes|fields)|affected_rows|re(sult|al_escape_string)|get_(server_info|host_info|client_info|proto_info))\\b", + "name": "support.function.mysql.php" + }, + { + "match": "(?i)\\bmysqli_(s(sl_set|t(ore_result|at|mt_(s(tore_result|end_long_data)|next_result|close|init|data_seek|prepare|execute|f(etch|ree_result)|attr_(set|get)|res(ult_metadata|et)|get_(warnings|result)|more_results|bind_(param|result)))|e(nd_(query|long_data)|t_(charset|opt|local_infile_(handler|default))|lect_db)|lave_query|avepoint)|next_result|c(ha(nge_user|racter_set_name)|o(nnect|mmit)|l(ient_encoding|ose))|thread_safe|init|options|d(isable_r(pl_parse|eads_from_master)|ump_debug_info|ebug|ata_seek)|use_result|p(ing|oll|aram_count|repare)|e(scape_string|nable_r(pl_parse|eads_from_master)|xecute|mbedded_server_(start|end))|kill|query|f(ield_seek|etch(_(object|field(s|_direct)?|a(ssoc|ll|rray)|row))?|ree_result)|autocommit|r(ollback|pl_(p(arse_enabled|robe)|query_type)|e(port|fresh|lease_savepoint|a(p_async_query|l_(connect|escape_string|query))))|get_(c(harset|onnection_stats|lient_(stats|info|version)|ache_stats)|warnings|links_stats|metadata)|m(ore_results|ulti_query|aster_query)|b(ind_(param|result)|egin_transaction))\\b", + "name": "support.function.mysqli.php" + }, + { + "match": "(?i)\\bmysqlnd_memcache_(set|get_config)\\b", + "name": "support.function.mysqlnd-memcache.php" + }, + { + "match": "(?i)\\bmysqlnd_ms_(set_(user_pick_server|qos)|dump_servers|query_is_select|fabric_select_(shard|global)|get_(stats|last_(used_connection|gtid))|xa_(commit|rollback|gc|begin)|match_wild)\\b", + "name": "support.function.mysqlnd-ms.php" + }, + { + "match": "(?i)\\bmysqlnd_qc_(set_(storage_handler|cache_condition|is_select|user_handlers)|clear_cache|get_(normalized_query_trace_log|c(ore_stats|ache_info)|query_trace_log|available_handlers))\\b", + "name": "support.function.mysqlnd-qc.php" + }, + { + "match": "(?i)\\bmysqlnd_uh_(set_(statement_proxy|connection_proxy)|convert_to_mysqlnd)\\b", + "name": "support.function.mysqlnd-uh.php" + }, + { + "match": "(?i)\\b(s(yslog|ocket_(set_(timeout|blocking)|get_status)|et(cookie|rawcookie))|h(ttp_response_code|eader(s_(sent|list)|_re(gister_callback|move))?)|c(heckdnsrr|loselog)|i(net_(ntop|pton)|p2long)|openlog|d(ns_(check_record|get_(record|mx))|efine_syslog_variables)|pfsockopen|fsockopen|long2ip|get(servby(name|port)|host(name|by(name(l)?|addr))|protobyn(umber|ame)|mxrr))\\b", + "name": "support.function.network.php" + }, + { + "match": "(?i)\\bnsapi_(virtual|re(sponse_headers|quest_headers))\\b", + "name": "support.function.nsapi.php" + }, + { + "match": "(?i)\\boci(s(tatementtype|e(tprefetch|rverversion)|avelob(file)?)|n(umcols|ew(c(ollection|ursor)|descriptor)|logon)|c(o(l(umn(s(cale|ize)|name|type(raw)?|isnull|precision)|l(size|trim|a(ssign(elem)?|ppend)|getelem|max))|mmit)|loselob|ancel)|internaldebug|definebyname|_(s(tatement_type|e(t_(client_i(nfo|dentifier)|prefetch|edition|action|module_name)|rver_version))|n(um_(fields|rows)|ew_(c(o(nnect|llection)|ursor)|descriptor))|c(o(nnect|mmit)|l(ient_version|ose)|ancel)|internal_debug|define_by_name|p(connect|a(ssword_change|rse))|e(rror|xecute)|f(ield_(s(cale|ize)|name|type(_raw)?|is_null|precision)|etch(_(object|a(ssoc|ll|rray)|row))?|ree_(statement|descriptor))|lob_(copy|is_equal)|r(ollback|esult)|get_implicit_resultset|bind_(array_by_name|by_name))|p(logon|arse)|e(rror|xecute)|f(etch(statement|into)?|ree(statement|c(ollection|ursor)|desc))|write(temporarylob|lobtofile)|lo(adlob|go(n|ff))|r(o(wcount|llback)|esult)|bindbyname)\\b", + "name": "support.function.oci8.php" + }, + { + "match": "(?i)\\bopcache_(compile_file|invalidate|reset|get_(status|configuration))\\b", + "name": "support.function.opcache.php" + }, + { + "match": "(?i)\\bopenssl_(s(ign|pki_(new|export(_challenge)?|verify)|eal)|c(sr_(sign|new|export(_to_file)?|get_(subject|public_key))|ipher_iv_length)|open|d(h_compute_key|igest|ecrypt)|p(ublic_(decrypt|encrypt)|k(cs(12_(export(_to_file)?|read)|7_(sign|decrypt|encrypt|verify))|ey_(new|export(_to_file)?|free|get_(details|p(ublic|rivate))))|rivate_(decrypt|encrypt)|bkdf2)|e(ncrypt|rror_string)|verify|free_key|random_pseudo_bytes|get_(c(ipher_methods|ert_locations)|p(ublickey|rivatekey)|md_methods)|x509_(check(_private_key|purpose)|parse|export(_to_file)?|f(ingerprint|ree)|read))\\b", + "name": "support.function.openssl.php" + }, + { + "match": "(?i)\\b(o(utput_(add_rewrite_var|reset_rewrite_vars)|b_(start|clean|implicit_flush|end_(clean|flush)|flush|list_handlers|g(zhandler|et_(status|c(ontents|lean)|flush|le(ngth|vel)))))|flush)\\b", + "name": "support.function.output.php" + }, + { + "match": "(?i)\\bpassword_(hash|needs_rehash|verify|get_info)\\b", + "name": "support.function.password.php" + }, + { + "match": "(?i)\\bpcntl_(s(trerror|ig(nal(_dispatch)?|timedwait|procmask|waitinfo)|etpriority)|e(rrno|xec)|fork|w(stopsig|termsig|if(s(topped|ignaled)|exited)|exitstatus|ait(pid)?)|alarm|get(_last_error|priority))\\b", + "name": "support.function.pcntl.php" + }, + { + "match": "(?i)\\bpg_(s(ocket|e(nd_(prepare|execute|query(_params)?)|t_(client_encoding|error_verbosity)|lect))|host|num_(fields|rows)|c(o(n(sume_input|nect(ion_(status|reset|busy)|_poll)?|vert)|py_(to|from))|l(ient_encoding|ose)|ancel_query)|t(ty|ra(nsaction_status|ce))|insert|options|d(elete|bname)|u(n(trace|escape_bytea)|pdate)|p(connect|ing|ort|ut_line|arameter_status|repare)|e(scape_(string|identifier|literal|bytea)|nd_copy|xecute)|version|query(_params)?|f(ield_(size|n(um|ame)|t(ype(_oid)?|able)|is_null|prtlen)|etch_(object|a(ssoc|ll(_columns)?|rray)|r(ow|esult))|lush|ree_result)|l(o_(seek|c(lose|reate)|t(ell|runcate)|import|open|unlink|export|write|read(_all)?)|ast_(notice|oid|error))|affected_rows|result_(s(tatus|eek)|error(_field)?)|get_(notify|pid|result)|meta_data)\\b", + "name": "support.function.pgsql.php" + }, + { + "match": "(?i)\\b(virtual|apache_(setenv|note|child_terminate|lookup_uri|re(s(ponse_headers|et_timeout)|quest_headers)|get(_(version|modules)|env))|getallheaders)\\b", + "name": "support.function.php_apache.php" + }, + { + "match": "(?i)\\bdom_import_simplexml\\b", + "name": "support.function.php_dom.php" + }, + { + "match": "(?i)\\bftp_(s(sl_connect|ystype|i(te|ze)|et_option)|n(list|b_(continue|put|f(put|get)|get))|c(h(dir|mod)|onnect|dup|lose)|delete|p(ut|wd|asv)|exec|quit|f(put|get)|login|alloc|r(ename|aw(list)?|mdir)|get(_option)?|m(dtm|kdir))\\b", + "name": "support.function.php_ftp.php" + }, + { + "match": "(?i)\\bimap_(s(can(mailbox)?|tatus|ort|ubscribe|e(t(_quota|flag_full|acl)|arch)|avebody)|header(s|info)?|num_(recent|msg)|c(heck|l(ose|earflag_full)|reate(mailbox)?)|t(hread|imeout)|open|delete(mailbox)?|8bit|u(n(subscribe|delete)|tf(7_(decode|encode)|8)|id)|ping|e(rrors|xpunge)|qprint|fetch(structure|header|text|_overview|mime|body)|l(sub|ist(s(can|ubscribed)|mailbox)?|ast_error)|a(ppend|lerts)|r(e(name(mailbox)?|open)|fc822_(parse_(headers|adrlist)|write_address))|g(c|et(subscribed|_quota(root)?|acl|mailboxes))|m(sgno|ime_header_decode|ail(_(co(py|mpose)|move)|boxmsginfo)?)|b(inary|ody(struct)?|ase64))\\b", + "name": "support.function.php_imap.php" + }, + { + "match": "(?i)\\bmssql_(select_db|n(um_(fields|rows)|ext_result)|c(onnect|lose)|init|data_seek|pconnect|execute|query|f(ield_(seek|name|type|length)|etch_(object|field|a(ssoc|rray)|row|batch)|ree_(statement|result))|r(ows_affected|esult)|g(uid_string|et_last_message)|min_(error_severity|message_severity)|bind)\\b", + "name": "support.function.php_mssql.php" + }, + { + "match": "(?i)\\bodbc_(s(tatistics|pecialcolumns|etoption)|n(um_(fields|rows)|ext_result)|c(o(nnect|lumn(s|privileges)|mmit)|ursor|lose(_all)?)|table(s|privileges)|d(o|ata_source)|p(connect|r(imarykeys|ocedure(s|columns)|epare))|e(rror(msg)?|xec(ute)?)|f(ield_(scale|n(um|ame)|type|precision|len)|oreignkeys|etch_(into|object|array|row)|ree_result)|longreadlen|autocommit|r(ollback|esult(_all)?)|gettypeinfo|binmode)\\b", + "name": "support.function.php_odbc.php" + }, + { + "match": "(?i)\\bpreg_(split|quote|filter|last_error|replace(_callback)?|grep|match(_all)?)\\b", + "name": "support.function.php_pcre.php" + }, + { + "match": "(?i)\\b(spl_(classes|object_hash|autoload(_(call|unregister|extensions|functions|register))?)|class_(implements|uses|parents)|iterator_(count|to_array|apply))\\b", + "name": "support.function.php_spl.php" + }, + { + "match": "(?i)\\bzip_(close|open|entry_(name|c(ompress(ionmethod|edsize)|lose)|open|filesize|read)|read)\\b", + "name": "support.function.php_zip.php" + }, + { + "match": "(?i)\\bposix_(s(trerror|et(sid|uid|pgid|e(uid|gid)|gid))|ctermid|t(tyname|imes)|i(satty|nitgroups)|uname|errno|kill|access|get(sid|cwd|uid|_last_error|p(id|pid|w(nam|uid)|g(id|rp))|e(uid|gid)|login|rlimit|g(id|r(nam|oups|gid)))|mk(nod|fifo))\\b", + "name": "support.function.posix.php" + }, + { + "match": "(?i)\\bset(threadtitle|proctitle)\\b", + "name": "support.function.proctitle.php" + }, + { + "match": "(?i)\\bpspell_(s(tore_replacement|uggest|ave_wordlist)|new(_(config|personal))?|c(heck|onfig_(save_repl|create|ignore|d(ict_dir|ata_dir)|personal|r(untogether|epl)|mode)|lear_session)|add_to_(session|personal))\\b", + "name": "support.function.pspell.php" + }, + { + "match": "(?i)\\breadline(_(c(ompletion_function|lear_history|allback_(handler_(install|remove)|read_char))|info|on_new_line|write_history|list_history|add_history|re(display|ad_history)))?\\b", + "name": "support.function.readline.php" + }, + { + "match": "(?i)\\brecode(_(string|file))?\\b", + "name": "support.function.recode.php" + }, + { + "match": "(?i)\\brrd(c_disconnect|_(create|tune|info|update|error|version|f(irst|etch)|last(update)?|restore|graph|xport))\\b", + "name": "support.function.rrd.php" + }, + { + "match": "(?i)\\b(s(hm_(has_var|detach|put_var|attach|remove(_var)?|get_var)|em_(acquire|re(lease|move)|get))|ftok|msg_(s(tat_queue|e(nd|t_queue))|queue_exists|re(ceive|move_queue)|get_queue))\\b", + "name": "support.function.sem.php" + }, + { + "match": "(?i)\\bsession_(s(ta(tus|rt)|et_(save_handler|cookie_params)|ave_path)|name|c(ommit|ache_(expire|limiter))|i(s_registered|d)|de(stroy|code)|un(set|register)|encode|write_close|abort|re(set|g(ister(_shutdown)?|enerate_id))|get_cookie_params|module_name)\\b", + "name": "support.function.session.php" + }, + { + "match": "(?i)\\bshmop_(size|close|open|delete|write|read)\\b", + "name": "support.function.shmop.php" + }, + { + "match": "(?i)\\bsimplexml_(import_dom|load_(string|file))\\b", + "name": "support.function.simplexml.php" + }, + { + "match": "(?i)\\bsnmp(set|2_(set|walk|real_walk|get(next)?)|_(set_(oid_(numeric_print|output_format)|enum_print|valueretrieval|quick_print)|read_mib|get_(valueretrieval|quick_print))|3_(set|walk|real_walk|get(next)?)|walk(oid)?|realwalk|get(next)?)\\b", + "name": "support.function.snmp.php" + }, + { + "match": "(?i)\\b(is_soap_fault|use_soap_error_handler)\\b", + "name": "support.function.soap.php" + }, + { + "match": "(?i)\\bsocket_(s(hutdown|trerror|e(nd(to|msg)?|t_(nonblock|option|block)|lect))|c(onnect|l(ose|ear_error)|reate(_(pair|listen))?|msg_space)|import_stream|write|l(isten|ast_error)|accept|re(cv(from|msg)?|ad)|get(sockname|_option|peername)|bind)\\b", + "name": "support.function.sockets.php" + }, + { + "match": "(?i)\\bsqlite_(s(ingle_query|eek)|has_(prev|more)|n(um_(fields|rows)|ext)|c(hanges|olumn|urrent|lose|reate_(function|aggregate))|open|u(nbuffered_query|df_(decode_binary|encode_binary))|p(open|rev)|e(scape_string|rror_string|xec)|valid|key|query|f(ield_name|etch_(s(tring|ingle)|column_types|object|a(ll|rray))|actory)|l(ib(encoding|version)|ast_(insert_rowid|error))|array_query|rewind|busy_timeout)\\b", + "name": "support.function.sqlite.php" + }, + { + "match": "(?i)\\bsqlsrv_(se(nd_stream_data|rver_info)|has_rows|n(um_(fields|rows)|ext_result)|c(o(n(nect|figure)|mmit)|l(ient_info|ose)|ancel)|prepare|e(rrors|xecute)|query|f(ield_metadata|etch(_(object|array))?|ree_stmt)|ro(ws_affected|llback)|get_(config|field)|begin_transaction)\\b", + "name": "support.function.sqlsrv.php" + }, + { + "match": "(?i)\\bstats_(s(ta(ndard_deviation|t_(noncentral_t|correlation|in(nerproduct|dependent_t)|p(owersum|ercentile|aired_t)|gennch|binomial_coef))|kew)|harmonic_mean|c(ovariance|df_(n(oncentral_(chisquare|f)|egative_binomial)|c(hisquare|auchy)|t|uniform|poisson|exponential|f|weibull|l(ogistic|aplace)|gamma|b(inomial|eta)))|den(s_(n(ormal|egative_binomial)|c(hisquare|auchy)|t|pmf_(hypergeometric|poisson|binomial)|exponential|f|weibull|l(ogistic|aplace)|gamma|beta)|_uniform)|variance|kurtosis|absolute_deviation|rand_(setall|phrase_to_seeds|ranf|ge(n_(no(ncen(tral_(t|f)|ral_chisquare)|rmal)|chisquare|t|i(nt|uniform|poisson|binomial(_negative)?)|exponential|f(uniform)?|gamma|beta)|t_seeds)))\\b", + "name": "support.function.stats.php" + }, + { + "match": "(?i)\\bs(tream_(s(ocket_(s(hutdown|e(ndto|rver))|client|pair|enable_crypto|accept|recvfrom|get_name)|upports_lock|e(t_(chunk_size|timeout|write_buffer|read_buffer|blocking)|lect))|notification_callback|co(ntext_(set_(option|default|params)|create|get_(options|default|params))|py_to_stream)|is_local|encoding|filter_(prepend|append|re(gister|move))|wrapper_(unregister|re(store|gister))|re(solve_include_path|gister_wrapper)|get_(contents|transports|filters|wrappers|line|meta_data)|bucket_(new|prepend|append|make_writeable))|et_socket_blocking)\\b", + "name": "support.function.streamsfuncs.php" + }, + { + "match": "(?i)\\b(s(scanf|ha1(_file)?|tr(s(tr|pn)|n(c(asecmp|mp)|atc(asecmp|mp))|c(spn|hr|oll|asecmp|mp)|t(o(upper|k|lower)|r)|i(str|p(slashes|cslashes|os|_tags))|_(s(huffle|plit)|ireplace|pad|word_count|r(ot13|ep(eat|lace))|getcsv)|p(os|brk)|len|r(chr|ipos|pos|ev))|imilar_text|oundex|ubstr(_(co(unt|mpare)|replace))?|printf|etlocale)|h(tml(specialchars(_decode)?|_entity_decode|entities)|e(x2bin|brev(c)?))|n(umber_format|l(2br|_langinfo))|c(h(op|unk_split|r)|o(nvert_(cyr_string|uu(decode|encode))|unt_chars)|r(ypt|c32))|trim|implode|ord|uc(first|words)|join|p(arse_str|rint(f)?)|e(cho|xplode)|v(sprintf|printf|fprintf)|quote(d_printable_(decode|encode)|meta)|fprintf|wordwrap|l(cfirst|trim|ocaleconv|evenshtein)|add(slashes|cslashes)|rtrim|get_html_translation_table|m(oney_format|d5(_file)?|etaphone)|bin2hex)\\b", + "name": "support.function.string.php" + }, + { + "match": "(?i)\\bsybase_(se(t_message_handler|lect_db)|num_(fields|rows)|c(onnect|lose)|d(eadlock_retry_count|ata_seek)|unbuffered_query|pconnect|query|f(ield_seek|etch_(object|field|a(ssoc|rray)|row)|ree_result)|affected_rows|result|get_last_message|min_(server_severity|client_severity|error_severity|message_severity))\\b", + "name": "support.function.sybase.php" + }, + { + "match": "(?i)\\b(taint|is_tainted|untaint)\\b", + "name": "support.function.taint.php" + }, + { + "match": "(?i)\\b(tidy_(s(et(opt|_encoding)|ave_config)|c(onfig_count|lean_repair)|is_x(html|ml)|diagnose|parse_(string|file)|error_count|warning_count|load_config|access_count|re(set_config|pair_(string|file))|get(opt|_(status|h(tml(_ver)?|ead)|config|o(utput|pt_doc)|r(oot|elease)|body)))|ob_tidyhandler)\\b", + "name": "support.function.tidy.php" + }, + { + "match": "(?i)\\btoken_(name|get_all)\\b", + "name": "support.function.tokenizer.php" + }, + { + "match": "(?i)\\btrader_(s(t(och(f|rsi)?|ddev)|in(h)?|u(m|b)|et_(compat|unstable_period)|qrt|ar(ext)?|ma)|ht_(sine|trend(line|mode)|dcp(hase|eriod)|phasor)|natr|c(ci|o(s(h)?|rrel)|dl(s(ho(otingstar|rtline)|t(icksandwich|alledpattern)|pinningtop|eparatinglines)|h(i(kkake(mod)?|ghwave)|omingpigeon|a(ngingman|rami(cross)?|mmer))|c(o(ncealbabyswall|unterattack)|losingmarubozu)|t(hrusting|a(sukigap|kuri)|ristar)|i(n(neck|vertedhammer)|dentical3crows)|2crows|onneck|d(oji(star)?|arkcloudcover|ragonflydoji)|u(nique3river|psidegap2crows)|3(starsinsouth|inside|outside|whitesoldiers|linestrike|blackcrows)|piercing|e(ngulfing|vening(star|dojistar))|kicking(bylength)?|l(ongl(ine|eggeddoji)|adderbottom)|a(dvanceblock|bandonedbaby)|ri(sefall3methods|ckshawman)|g(apsidesidewhite|ravestonedoji)|xsidegap3methods|m(orning(star|dojistar)|a(t(hold|chinglow)|rubozu))|b(elthold|reakaway))|eil|mo)|t(sf|ypprice|3|ema|an(h)?|r(i(x|ma)|ange))|obv|d(iv|ema|x)|ultosc|p(po|lus_d(i|m))|e(rrno|xp|ma)|var|kama|floor|w(clprice|illr|ma)|l(n|inearreg(_(slope|intercept|angle))?|og10)|a(sin|cos|t(an|r)|d(osc|d|x(r)?)?|po|vgprice|roon(osc)?)|r(si|oc(p|r(100)?)?)|get_(compat|unstable_period)|m(i(n(index|us_d(i|m)|max(index)?)?|dp(oint|rice))|om|ult|edprice|fi|a(cd(ext|fix)?|vp|x(index)?|ma)?)|b(op|eta|bands))\\b", + "name": "support.function.trader.php" + }, + { + "match": "(?i)\\buopz_(co(py|mpose)|implement|overload|delete|undefine|extend|f(unction|lags)|re(store|name|define)|backup)\\b", + "name": "support.function.uopz.php" + }, + { + "match": "(?i)\\b(http_build_query|url(decode|encode)|parse_url|rawurl(decode|encode)|get_(headers|meta_tags)|base64_(decode|encode))\\b", + "name": "support.function.url.php" + }, + { + "match": "(?i)\\b(s(trval|e(ttype|rialize))|i(s(set|_(s(calar|tring)|nu(ll|meric)|callable|int(eger)?|object|double|float|long|array|re(source|al)|bool))|ntval|mport_request_variables)|d(oubleval|ebug_zval_dump)|unse(t|rialize)|print_r|empty|var_(dump|export)|floatval|get(type|_(defined_vars|resource_type))|boolval)\\b", + "name": "support.function.var.php" + }, + { + "match": "(?i)\\bwddx_(serialize_va(lue|rs)|deserialize|packet_(start|end)|add_vars)\\b", + "name": "support.function.wddx.php" + }, + { + "match": "(?i)\\bxhprof_(sample_(disable|enable)|disable|enable)\\b", + "name": "support.function.xhprof.php" + }, + { + "match": "(?i)\\b(utf8_(decode|encode)|xml_(set_(start_namespace_decl_handler|notation_decl_handler|character_data_handler|object|default_handler|unparsed_entity_decl_handler|processing_instruction_handler|e(nd_namespace_decl_handler|lement_handler|xternal_entity_ref_handler))|parse(_into_struct|r_(set_option|create(_ns)?|free|get_option))?|error_string|get_(current_(column_number|line_number|byte_index)|error_code)))\\b", + "name": "support.function.xml.php" + }, + { + "match": "(?i)\\bxmlrpc_(se(t_type|rver_(c(all_method|reate)|destroy|add_introspection_data|register_(introspection_callback|method)))|is_fault|decode(_request)?|parse_method_descriptions|encode(_request)?|get_type)\\b", + "name": "support.function.xmlrpc.php" + }, + { + "match": "(?i)\\bxmlwriter_(s(tart_(c(omment|data)|d(td(_(e(ntity|lement)|attlist))?|ocument)|pi|element(_ns)?|attribute(_ns)?)|et_indent(_string)?)|text|o(utput_memory|pen_(uri|memory))|end_(c(omment|data)|d(td(_(e(ntity|lement)|attlist))?|ocument)|pi|element|attribute)|f(ull_end_element|lush)|write_(c(omment|data)|dtd(_(e(ntity|lement)|attlist))?|pi|element(_ns)?|attribute(_ns)?|raw))\\b", + "name": "support.function.xmlwriter.php" + }, + { + "match": "(?i)\\b(zlib_(decode|encode|get_coding_type)|readgzfile|gz(seek|c(ompress|lose)|tell|inflate|open|de(code|flate)|uncompress|p(uts|assthru)|e(ncode|of)|file|write|re(wind|ad)|get(s(s)?|c)))\\b", + "name": "support.function.zlib.php" + }, + { + "match": "(?i)\\bis_int(eger)?\\b", + "name": "support.function.alias.php" + } + ] + }, + "user-function-call": { + "begin": "(?i)(?=[a-z_0-9\\\\]*[a-z_][a-z0-9_]*\\s*\\()", + "end": "(?i)[a-z_][a-z_0-9]*(?=\\s*\\()", + "name": "meta.function-call.php", + "patterns": [ + { + "include": "#namespace" + } + ] + }, + "var_basic": { + "patterns": [ + { + "captures": { + "1": { + "name": "punctuation.definition.variable.php" + } + }, + "match": "(?x)\n \t\t\t (\\$+)[a-zA-Z_\\x{7f}-\\x{ff}]\n \t\t\t [a-zA-Z0-9_\\x{7f}-\\x{ff}]*?\\b", + "name": "variable.other.php" + } + ] + }, + "var_global": { + "captures": { + "1": { + "name": "punctuation.definition.variable.php" + } + }, + "match": "(\\$)((_(COOKIE|FILES|GET|POST|REQUEST))|arg(v|c))\\b", + "name": "variable.other.global.php" + }, + "var_global_safer": { + "captures": { + "1": { + "name": "punctuation.definition.variable.php" + } + }, + "match": "(\\$)((GLOBALS|_(ENV|SERVER|SESSION)))", + "name": "variable.other.global.safer.php" + }, + "variable-name": { + "patterns": [ + { + "include": "#var_global" + }, + { + "include": "#var_global_safer" + }, + { + "captures": { + "1": { + "name": "variable.other.php" + }, + "2": { + "name": "punctuation.definition.variable.php" + }, + "4": { + "name": "keyword.operator.class.php" + }, + "5": { + "name": "variable.other.property.php" + }, + "6": { + "name": "punctuation.section.array.begin.php" + }, + "7": { + "name": "constant.numeric.index.php" + }, + "8": { + "name": "variable.other.index.php" + }, + "9": { + "name": "punctuation.definition.variable.php" + }, + "10": { + "name": "string.unquoted.index.php" + }, + "11": { + "name": "punctuation.section.array.end.php" + } + }, + "comment": "Simple syntax: $foo, $foo[0], $foo[$bar], $foo->bar", + "match": "(?x)\n\t\t\t\t\t\t((\\$)(?[a-zA-Z_\\x{7f}-\\x{ff}][a-zA-Z0-9_\\x{7f}-\\x{ff}]*))\n\t\t\t\t\t\t(?:\n\t\t\t\t\t\t\t(->)(\\g)\n\t\t\t\t\t\t\t|\n\t\t\t\t\t\t\t(\\[)\n\t\t\t\t\t\t\t\t(?:(\\d+)|((\\$)\\g)|(\\w+))\n\t\t\t\t\t\t\t(\\])\n\t\t\t\t\t\t)?\n\t\t\t\t\t\t" + }, + { + "captures": { + "1": { + "name": "variable.other.php" + }, + "2": { + "name": "punctuation.definition.variable.php" + }, + "4": { + "name": "punctuation.definition.variable.php" + } + }, + "comment": "Simple syntax with braces: \"foo${bar}baz\"", + "match": "(?x)\n\t\t\t\t\t\t((\\$\\{)(?[a-zA-Z_\\x{7f}-\\x{ff}][a-zA-Z0-9_\\x{7f}-\\x{ff}]*)(\\}))\n\t\t\t\t\t\t" + } + ] + }, + "variables": { + "patterns": [ + { + "include": "#var_global" + }, + { + "include": "#var_global_safer" + }, + { + "include": "#var_basic" + }, + { + "begin": "(\\$\\{)(?=.*?\\})", + "beginCaptures": { + "1": { + "name": "punctuation.definition.variable.php" + } + }, + "end": "(\\})", + "endCaptures": { + "1": { + "name": "punctuation.definition.variable.php" + } + }, + "patterns": [ + { + "include": "#language" + } + ] + } + ] + } + } +} \ No newline at end of file diff --git a/extensions/php/test/colorize-results/test_php.json b/extensions/php/test/colorize-results/test_php.json index 1a5ea5ae44e..a94e067f55c 100644 --- a/extensions/php/test/colorize-results/test_php.json +++ b/extensions/php/test/colorize-results/test_php.json @@ -1,7 +1,7 @@ [ { "c": "<", - "t": "begin.definition.html.meta.punctuation.tag", + "t": "any.definition.html.meta.punctuation.structure.tag", "r": { "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.meta.tag rgb(128, 128, 128)", "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.meta.tag rgb(128, 0, 0)", @@ -12,7 +12,7 @@ }, { "c": "html", - "t": "entity.name.tag.tag-html", + "t": "any.entity.html.meta.name.structure.tag", "r": { "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.entity.name.tag rgb(86, 156, 214)", "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.entity.name.tag rgb(128, 0, 0)", @@ -23,7 +23,7 @@ }, { "c": ">", - "t": "begin.definition.html.meta.punctuation.tag", + "t": "any.definition.html.meta.punctuation.structure.tag", "r": { "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.meta.tag rgb(128, 128, 128)", "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.meta.tag rgb(128, 0, 0)", @@ -34,7 +34,7 @@ }, { "c": "<", - "t": "begin.definition.html.meta.punctuation.tag", + "t": "any.definition.html.meta.punctuation.structure.tag", "r": { "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.meta.tag rgb(128, 128, 128)", "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.meta.tag rgb(128, 0, 0)", @@ -45,7 +45,7 @@ }, { "c": "head", - "t": "entity.name.tag.tag-head", + "t": "any.entity.html.meta.name.structure.tag", "r": { "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.entity.name.tag rgb(86, 156, 214)", "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.entity.name.tag rgb(128, 0, 0)", @@ -56,7 +56,7 @@ }, { "c": ">", - "t": "begin.definition.html.meta.punctuation.tag", + "t": "any.definition.html.meta.punctuation.structure.tag", "r": { "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.meta.tag rgb(128, 128, 128)", "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.meta.tag rgb(128, 0, 0)", @@ -78,7 +78,7 @@ }, { "c": "<", - "t": "begin.definition.html.meta.punctuation.tag", + "t": "any.begin.definition.html.inline.meta.punctuation.tag", "r": { "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.meta.tag rgb(128, 128, 128)", "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.meta.tag rgb(128, 0, 0)", @@ -89,7 +89,7 @@ }, { "c": "title", - "t": "entity.name.tag.tag-title", + "t": "any.entity.html.inline.meta.name.tag", "r": { "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.entity.name.tag rgb(86, 156, 214)", "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.entity.name.tag rgb(128, 0, 0)", @@ -100,7 +100,7 @@ }, { "c": ">", - "t": "begin.definition.html.meta.punctuation.tag", + "t": "any.definition.end.html.inline.meta.punctuation.tag", "r": { "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.meta.tag rgb(128, 128, 128)", "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.meta.tag rgb(128, 0, 0)", @@ -122,7 +122,7 @@ }, { "c": "", - "t": "definition.end.html.meta.punctuation.tag", + "t": "any.definition.end.html.inline.meta.punctuation.tag", "r": { "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.meta.tag rgb(128, 128, 128)", "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.meta.tag rgb(128, 0, 0)", @@ -155,7 +155,7 @@ }, { "c": "", - "t": "definition.end.html.meta.punctuation.tag", + "t": "any.definition.html.meta.punctuation.structure.tag", "r": { "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.meta.tag rgb(128, 128, 128)", "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.meta.tag rgb(128, 0, 0)", @@ -188,7 +188,7 @@ }, { "c": "<", - "t": "begin.definition.html.meta.punctuation.tag", + "t": "any.definition.html.meta.punctuation.structure.tag", "r": { "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.meta.tag rgb(128, 128, 128)", "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.meta.tag rgb(128, 0, 0)", @@ -199,7 +199,7 @@ }, { "c": "body", - "t": "entity.name.tag.tag-body", + "t": "any.entity.html.meta.name.structure.tag", "r": { "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.entity.name.tag rgb(86, 156, 214)", "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.entity.name.tag rgb(128, 0, 0)", @@ -210,7 +210,7 @@ }, { "c": ">", - "t": "begin.definition.html.meta.punctuation.tag", + "t": "any.definition.html.meta.punctuation.structure.tag", "r": { "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.meta.tag rgb(128, 128, 128)", "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.meta.tag rgb(128, 0, 0)", @@ -221,7 +221,7 @@ }, { "c": "\"", - "t": "php.string", + "c": "(", + "t": "block.embedded.meta.php.source", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "\"", + "t": "begin.block.definition.double.embedded.meta.php.punctuation.quoted.source.string", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.string rgb(206, 145, 120)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.string rgb(163, 21, 21)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "Starting point for cut cards is: ", + "t": "block.double.embedded.meta.php.quoted.source.string.string-contents", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.string rgb(206, 145, 120)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.string rgb(163, 21, 21)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "$", + "t": "block.definition.double.embedded.meta.other.php.punctuation.quoted.source.string.string-contents.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "starting_point", + "t": "block.double.embedded.meta.other.php.quoted.source.string.string-contents.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "

", + "t": "block.double.embedded.meta.php.quoted.source.string.string-contents", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.string rgb(206, 145, 120)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.string rgb(163, 21, 21)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "\"", + "t": "block.definition.double.embedded.end.meta.php.punctuation.quoted.source.string", "r": { "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.string rgb(206, 145, 120)", "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.string rgb(163, 21, 21)", @@ -2003,7 +2443,7 @@ }, { "c": ")", - "t": "delimiter.parenthesis.php", + "t": "block.embedded.meta.php.source", "r": { "dark_plus": ".vs-dark .token rgb(212, 212, 212)", "light_plus": ".vs .token rgb(0, 0, 0)", @@ -2014,7 +2454,7 @@ }, { "c": ";", - "t": "delimiter.php", + "t": "block.embedded.expression.meta.php.punctuation.source.terminator", "r": { "dark_plus": ".vs-dark .token rgb(212, 212, 212)", "light_plus": ".vs .token rgb(0, 0, 0)", @@ -2025,18 +2465,29 @@ }, { "c": "\t", - "t": "", + "t": "block.comment.embedded.leading.meta.php.punctuation.source.whitespace", "r": { - "dark_plus": ".vs-dark .token rgb(212, 212, 212)", - "light_plus": ".vs .token rgb(0, 0, 0)", - "dark_vs": ".vs-dark .token rgb(212, 212, 212)", - "light_vs": ".vs .token rgb(0, 0, 0)", - "hc_black": ".hc-black .token rgb(255, 255, 255)" + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.comment rgba(227, 228, 226, 0.156863)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.comment rgba(51, 51, 51, 0.2)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.comment rgba(227, 228, 226, 0.156863)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.comment rgba(51, 51, 51, 0.2)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.comment rgba(227, 228, 226, 0.156863)" } }, { - "c": "// display shuffled cards (EXAMPLE ONLY)", - "t": "comment.php", + "c": "//", + "t": "block.comment.definition.double-slash.embedded.line.meta.php.punctuation.source", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.comment rgb(96, 139, 78)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.comment rgb(0, 128, 0)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.comment rgb(96, 139, 78)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.comment rgb(0, 128, 0)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.comment rgb(124, 166, 104)" + } + }, + { + "c": " display shuffled cards (EXAMPLE ONLY)", + "t": "block.comment.double-slash.embedded.line.meta.php.source", "r": { "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.comment rgb(96, 139, 78)", "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.comment rgb(0, 128, 0)", @@ -2047,7 +2498,7 @@ }, { "c": "\t", - "t": "", + "t": "block.embedded.meta.php.source", "r": { "dark_plus": ".vs-dark .token rgb(212, 212, 212)", "light_plus": ".vs .token rgb(0, 0, 0)", @@ -2058,18 +2509,18 @@ }, { "c": "for", - "t": "keyword.php", + "t": "block.control.embedded.keyword.meta.php.source", "r": { - "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.keyword rgb(86, 156, 214)", - "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.keyword rgb(0, 0, 255)", - "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.keyword rgb(86, 156, 214)", - "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.keyword rgb(0, 0, 255)", - "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.keyword rgb(86, 156, 214)" + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.keyword.control rgb(197, 134, 192)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.keyword.control rgb(175, 0, 219)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.keyword.control rgb(86, 156, 214)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.keyword.control rgb(0, 0, 255)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.keyword.control rgb(86, 156, 214)" } }, { - "c": " ", - "t": "", + "c": " (", + "t": "block.embedded.meta.php.source", "r": { "dark_plus": ".vs-dark .token rgb(212, 212, 212)", "light_plus": ".vs .token rgb(0, 0, 0)", @@ -2079,19 +2530,19 @@ } }, { - "c": "(", - "t": "delimiter.parenthesis.php", + "c": "$", + "t": "block.definition.embedded.meta.other.php.punctuation.source.variable", "r": { - "dark_plus": ".vs-dark .token rgb(212, 212, 212)", - "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", "dark_vs": ".vs-dark .token rgb(212, 212, 212)", "light_vs": ".vs .token rgb(0, 0, 0)", "hc_black": ".hc-black .token rgb(255, 255, 255)" } }, { - "c": "$index", - "t": "php.variable", + "c": "index", + "t": "block.embedded.meta.other.php.source.variable", "r": { "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", @@ -2102,7 +2553,7 @@ }, { "c": " ", - "t": "", + "t": "block.embedded.meta.php.source", "r": { "dark_plus": ".vs-dark .token rgb(212, 212, 212)", "light_plus": ".vs .token rgb(0, 0, 0)", @@ -2113,18 +2564,18 @@ }, { "c": "=", - "t": "delimiter.php", + "t": "assignment.block.embedded.keyword.meta.operator.php.source", "r": { - "dark_plus": ".vs-dark .token rgb(212, 212, 212)", - "light_plus": ".vs .token rgb(0, 0, 0)", - "dark_vs": ".vs-dark .token rgb(212, 212, 212)", - "light_vs": ".vs .token rgb(0, 0, 0)", - "hc_black": ".hc-black .token rgb(255, 255, 255)" + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.keyword.operator rgb(212, 212, 212)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.keyword.operator rgb(0, 0, 0)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.keyword.operator rgb(212, 212, 212)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.keyword.operator rgb(0, 0, 0)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.keyword.operator rgb(212, 212, 212)" } }, { "c": " ", - "t": "", + "t": "block.embedded.meta.php.source", "r": { "dark_plus": ".vs-dark .token rgb(212, 212, 212)", "light_plus": ".vs .token rgb(0, 0, 0)", @@ -2135,18 +2586,18 @@ }, { "c": "0", - "t": "number.php", + "t": "block.constant.embedded.meta.numeric.php.source", "r": { - "dark_plus": ".vs-dark .token rgb(212, 212, 212)", - "light_plus": ".vs .token rgb(0, 0, 0)", - "dark_vs": ".vs-dark .token rgb(212, 212, 212)", - "light_vs": ".vs .token rgb(0, 0, 0)", - "hc_black": ".hc-black .token rgb(255, 255, 255)" + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.constant.numeric rgb(181, 206, 168)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.constant.numeric rgb(9, 136, 90)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.constant.numeric rgb(181, 206, 168)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.constant.numeric rgb(9, 136, 90)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.constant.numeric rgb(181, 206, 168)" } }, { "c": ";", - "t": "delimiter.php", + "t": "block.embedded.expression.meta.php.punctuation.source.terminator", "r": { "dark_plus": ".vs-dark .token rgb(212, 212, 212)", "light_plus": ".vs .token rgb(0, 0, 0)", @@ -2157,7 +2608,7 @@ }, { "c": " ", - "t": "", + "t": "block.embedded.meta.php.source", "r": { "dark_plus": ".vs-dark .token rgb(212, 212, 212)", "light_plus": ".vs .token rgb(0, 0, 0)", @@ -2167,8 +2618,19 @@ } }, { - "c": "$index", - "t": "php.variable", + "c": "$", + "t": "block.definition.embedded.meta.other.php.punctuation.source.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "index", + "t": "block.embedded.meta.other.php.source.variable", "r": { "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", @@ -2179,7 +2641,7 @@ }, { "c": " ", - "t": "", + "t": "block.embedded.meta.php.source", "r": { "dark_plus": ".vs-dark .token rgb(212, 212, 212)", "light_plus": ".vs .token rgb(0, 0, 0)", @@ -2190,18 +2652,18 @@ }, { "c": "<", - "t": "delimiter.php", + "t": "block.comparison.embedded.keyword.meta.operator.php.source", "r": { - "dark_plus": ".vs-dark .token rgb(212, 212, 212)", - "light_plus": ".vs .token rgb(0, 0, 0)", - "dark_vs": ".vs-dark .token rgb(212, 212, 212)", - "light_vs": ".vs .token rgb(0, 0, 0)", - "hc_black": ".hc-black .token rgb(255, 255, 255)" + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.keyword.operator rgb(212, 212, 212)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.keyword.operator rgb(0, 0, 0)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.keyword.operator rgb(212, 212, 212)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.keyword.operator rgb(0, 0, 0)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.keyword.operator rgb(212, 212, 212)" } }, { "c": " ", - "t": "", + "t": "block.embedded.meta.php.source", "r": { "dark_plus": ".vs-dark .token rgb(212, 212, 212)", "light_plus": ".vs .token rgb(0, 0, 0)", @@ -2212,18 +2674,18 @@ }, { "c": "52", - "t": "number.php", + "t": "block.constant.embedded.meta.numeric.php.source", "r": { - "dark_plus": ".vs-dark .token rgb(212, 212, 212)", - "light_plus": ".vs .token rgb(0, 0, 0)", - "dark_vs": ".vs-dark .token rgb(212, 212, 212)", - "light_vs": ".vs .token rgb(0, 0, 0)", - "hc_black": ".hc-black .token rgb(255, 255, 255)" + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.constant.numeric rgb(181, 206, 168)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.constant.numeric rgb(9, 136, 90)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.constant.numeric rgb(181, 206, 168)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.constant.numeric rgb(9, 136, 90)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.constant.numeric rgb(181, 206, 168)" } }, { "c": ";", - "t": "delimiter.php", + "t": "block.embedded.expression.meta.php.punctuation.source.terminator", "r": { "dark_plus": ".vs-dark .token rgb(212, 212, 212)", "light_plus": ".vs .token rgb(0, 0, 0)", @@ -2234,7 +2696,7 @@ }, { "c": " ", - "t": "", + "t": "block.embedded.meta.php.source", "r": { "dark_plus": ".vs-dark .token rgb(212, 212, 212)", "light_plus": ".vs .token rgb(0, 0, 0)", @@ -2244,8 +2706,19 @@ } }, { - "c": "$index", - "t": "php.variable", + "c": "$", + "t": "block.definition.embedded.meta.other.php.punctuation.source.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "index", + "t": "block.embedded.meta.other.php.source.variable", "r": { "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", @@ -2256,29 +2729,18 @@ }, { "c": "++", - "t": "delimiter.php", + "t": "block.embedded.increment-decrement.keyword.meta.operator.php.source", "r": { - "dark_plus": ".vs-dark .token rgb(212, 212, 212)", - "light_plus": ".vs .token rgb(0, 0, 0)", - "dark_vs": ".vs-dark .token rgb(212, 212, 212)", - "light_vs": ".vs .token rgb(0, 0, 0)", - "hc_black": ".hc-black .token rgb(255, 255, 255)" + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.keyword.operator rgb(212, 212, 212)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.keyword.operator rgb(0, 0, 0)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.keyword.operator rgb(212, 212, 212)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.keyword.operator rgb(0, 0, 0)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.keyword.operator rgb(212, 212, 212)" } }, { - "c": ")", - "t": "delimiter.parenthesis.php", - "r": { - "dark_plus": ".vs-dark .token rgb(212, 212, 212)", - "light_plus": ".vs .token rgb(0, 0, 0)", - "dark_vs": ".vs-dark .token rgb(212, 212, 212)", - "light_vs": ".vs .token rgb(0, 0, 0)", - "hc_black": ".hc-black .token rgb(255, 255, 255)" - } - }, - { - "c": " ", - "t": "", + "c": ") ", + "t": "block.embedded.meta.php.source", "r": { "dark_plus": ".vs-dark .token rgb(212, 212, 212)", "light_plus": ".vs .token rgb(0, 0, 0)", @@ -2289,7 +2751,7 @@ }, { "c": "{", - "t": "bracket.delimiter.php", + "t": "begin.block.embedded.meta.php.punctuation.scope.section.source", "r": { "dark_plus": ".vs-dark .token rgb(212, 212, 212)", "light_plus": ".vs .token rgb(0, 0, 0)", @@ -2300,7 +2762,7 @@ }, { "c": "\t\t", - "t": "", + "t": "block.embedded.meta.php.source", "r": { "dark_plus": ".vs-dark .token rgb(212, 212, 212)", "light_plus": ".vs .token rgb(0, 0, 0)", @@ -2311,18 +2773,18 @@ }, { "c": "if", - "t": "keyword.php", + "t": "block.control.embedded.keyword.meta.php.source", "r": { - "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.keyword rgb(86, 156, 214)", - "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.keyword rgb(0, 0, 255)", - "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.keyword rgb(86, 156, 214)", - "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.keyword rgb(0, 0, 255)", - "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.keyword rgb(86, 156, 214)" + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.keyword.control rgb(197, 134, 192)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.keyword.control rgb(175, 0, 219)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.keyword.control rgb(86, 156, 214)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.keyword.control rgb(0, 0, 255)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.keyword.control rgb(86, 156, 214)" } }, { - "c": " ", - "t": "", + "c": " (", + "t": "block.embedded.meta.php.source", "r": { "dark_plus": ".vs-dark .token rgb(212, 212, 212)", "light_plus": ".vs .token rgb(0, 0, 0)", @@ -2332,19 +2794,19 @@ } }, { - "c": "(", - "t": "delimiter.parenthesis.php", + "c": "$", + "t": "block.definition.embedded.meta.other.php.punctuation.source.variable", "r": { - "dark_plus": ".vs-dark .token rgb(212, 212, 212)", - "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", "dark_vs": ".vs-dark .token rgb(212, 212, 212)", "light_vs": ".vs .token rgb(0, 0, 0)", "hc_black": ".hc-black .token rgb(255, 255, 255)" } }, { - "c": "$starting_point", - "t": "php.variable", + "c": "starting_point", + "t": "block.embedded.meta.other.php.source.variable", "r": { "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", @@ -2355,7 +2817,7 @@ }, { "c": " ", - "t": "", + "t": "block.embedded.meta.php.source", "r": { "dark_plus": ".vs-dark .token rgb(212, 212, 212)", "light_plus": ".vs .token rgb(0, 0, 0)", @@ -2366,18 +2828,18 @@ }, { "c": "==", - "t": "delimiter.php", + "t": "block.comparison.embedded.keyword.meta.operator.php.source", "r": { - "dark_plus": ".vs-dark .token rgb(212, 212, 212)", - "light_plus": ".vs .token rgb(0, 0, 0)", - "dark_vs": ".vs-dark .token rgb(212, 212, 212)", - "light_vs": ".vs .token rgb(0, 0, 0)", - "hc_black": ".hc-black .token rgb(255, 255, 255)" + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.keyword.operator rgb(212, 212, 212)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.keyword.operator rgb(0, 0, 0)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.keyword.operator rgb(212, 212, 212)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.keyword.operator rgb(0, 0, 0)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.keyword.operator rgb(212, 212, 212)" } }, { "c": " ", - "t": "", + "t": "block.embedded.meta.php.source", "r": { "dark_plus": ".vs-dark .token rgb(212, 212, 212)", "light_plus": ".vs .token rgb(0, 0, 0)", @@ -2388,29 +2850,18 @@ }, { "c": "52", - "t": "number.php", + "t": "block.constant.embedded.meta.numeric.php.source", "r": { - "dark_plus": ".vs-dark .token rgb(212, 212, 212)", - "light_plus": ".vs .token rgb(0, 0, 0)", - "dark_vs": ".vs-dark .token rgb(212, 212, 212)", - "light_vs": ".vs .token rgb(0, 0, 0)", - "hc_black": ".hc-black .token rgb(255, 255, 255)" + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.constant.numeric rgb(181, 206, 168)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.constant.numeric rgb(9, 136, 90)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.constant.numeric rgb(181, 206, 168)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.constant.numeric rgb(9, 136, 90)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.constant.numeric rgb(181, 206, 168)" } }, { - "c": ")", - "t": "delimiter.parenthesis.php", - "r": { - "dark_plus": ".vs-dark .token rgb(212, 212, 212)", - "light_plus": ".vs .token rgb(0, 0, 0)", - "dark_vs": ".vs-dark .token rgb(212, 212, 212)", - "light_vs": ".vs .token rgb(0, 0, 0)", - "hc_black": ".hc-black .token rgb(255, 255, 255)" - } - }, - { - "c": " ", - "t": "", + "c": ") ", + "t": "block.embedded.meta.php.source", "r": { "dark_plus": ".vs-dark .token rgb(212, 212, 212)", "light_plus": ".vs .token rgb(0, 0, 0)", @@ -2421,7 +2872,7 @@ }, { "c": "{", - "t": "bracket.delimiter.php", + "t": "begin.block.embedded.meta.php.punctuation.scope.section.source", "r": { "dark_plus": ".vs-dark .token rgb(212, 212, 212)", "light_plus": ".vs .token rgb(0, 0, 0)", @@ -2432,7 +2883,7 @@ }, { "c": " ", - "t": "", + "t": "block.embedded.meta.php.source", "r": { "dark_plus": ".vs-dark .token rgb(212, 212, 212)", "light_plus": ".vs .token rgb(0, 0, 0)", @@ -2442,8 +2893,19 @@ } }, { - "c": "$starting_point", - "t": "php.variable", + "c": "$", + "t": "block.definition.embedded.meta.other.php.punctuation.source.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "starting_point", + "t": "block.embedded.meta.other.php.source.variable", "r": { "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", @@ -2454,7 +2916,7 @@ }, { "c": " ", - "t": "", + "t": "block.embedded.meta.php.source", "r": { "dark_plus": ".vs-dark .token rgb(212, 212, 212)", "light_plus": ".vs .token rgb(0, 0, 0)", @@ -2465,18 +2927,18 @@ }, { "c": "=", - "t": "delimiter.php", + "t": "assignment.block.embedded.keyword.meta.operator.php.source", "r": { - "dark_plus": ".vs-dark .token rgb(212, 212, 212)", - "light_plus": ".vs .token rgb(0, 0, 0)", - "dark_vs": ".vs-dark .token rgb(212, 212, 212)", - "light_vs": ".vs .token rgb(0, 0, 0)", - "hc_black": ".hc-black .token rgb(255, 255, 255)" + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.keyword.operator rgb(212, 212, 212)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.keyword.operator rgb(0, 0, 0)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.keyword.operator rgb(212, 212, 212)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.keyword.operator rgb(0, 0, 0)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.keyword.operator rgb(212, 212, 212)" } }, { "c": " ", - "t": "", + "t": "block.embedded.meta.php.source", "r": { "dark_plus": ".vs-dark .token rgb(212, 212, 212)", "light_plus": ".vs .token rgb(0, 0, 0)", @@ -2487,18 +2949,18 @@ }, { "c": "0", - "t": "number.php", + "t": "block.constant.embedded.meta.numeric.php.source", "r": { - "dark_plus": ".vs-dark .token rgb(212, 212, 212)", - "light_plus": ".vs .token rgb(0, 0, 0)", - "dark_vs": ".vs-dark .token rgb(212, 212, 212)", - "light_vs": ".vs .token rgb(0, 0, 0)", - "hc_black": ".hc-black .token rgb(255, 255, 255)" + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.constant.numeric rgb(181, 206, 168)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.constant.numeric rgb(9, 136, 90)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.constant.numeric rgb(181, 206, 168)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.constant.numeric rgb(9, 136, 90)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.constant.numeric rgb(181, 206, 168)" } }, { "c": ";", - "t": "delimiter.php", + "t": "block.embedded.expression.meta.php.punctuation.source.terminator", "r": { "dark_plus": ".vs-dark .token rgb(212, 212, 212)", "light_plus": ".vs .token rgb(0, 0, 0)", @@ -2509,7 +2971,7 @@ }, { "c": " ", - "t": "", + "t": "block.embedded.meta.php.source", "r": { "dark_plus": ".vs-dark .token rgb(212, 212, 212)", "light_plus": ".vs .token rgb(0, 0, 0)", @@ -2520,7 +2982,7 @@ }, { "c": "}", - "t": "bracket.delimiter.php", + "t": "block.embedded.end.meta.php.punctuation.scope.section.source", "r": { "dark_plus": ".vs-dark .token rgb(212, 212, 212)", "light_plus": ".vs .token rgb(0, 0, 0)", @@ -2531,7 +2993,7 @@ }, { "c": "\t\t", - "t": "", + "t": "block.embedded.meta.php.source", "r": { "dark_plus": ".vs-dark .token rgb(212, 212, 212)", "light_plus": ".vs .token rgb(0, 0, 0)", @@ -2542,18 +3004,7 @@ }, { "c": "print", - "t": "keyword.php", - "r": { - "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.keyword rgb(86, 156, 214)", - "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.keyword rgb(0, 0, 255)", - "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.keyword rgb(86, 156, 214)", - "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.keyword rgb(0, 0, 255)", - "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.keyword rgb(86, 156, 214)" - } - }, - { - "c": "(", - "t": "delimiter.parenthesis.php", + "t": "block.construct.embedded.function.meta.output.php.source.support", "r": { "dark_plus": ".vs-dark .token rgb(212, 212, 212)", "light_plus": ".vs .token rgb(0, 0, 0)", @@ -2563,8 +3014,118 @@ } }, { - "c": "\"Uncut Point: $deck[$index] \"", - "t": "php.string", + "c": "(", + "t": "block.embedded.meta.php.source", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "\"", + "t": "begin.block.definition.double.embedded.meta.php.punctuation.quoted.source.string", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.string rgb(206, 145, 120)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.string rgb(163, 21, 21)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "Uncut Point: ", + "t": "block.double.embedded.meta.php.quoted.source.string.string-contents", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.string rgb(206, 145, 120)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.string rgb(163, 21, 21)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "$", + "t": "block.definition.double.embedded.meta.other.php.punctuation.quoted.source.string.string-contents.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "deck", + "t": "block.double.embedded.meta.other.php.quoted.source.string.string-contents.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "[", + "t": "array.begin.block.double.embedded.meta.php.punctuation.quoted.section.source.string.string-contents", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.string rgb(206, 145, 120)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.string rgb(163, 21, 21)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "$", + "t": "block.definition.double.embedded.index.meta.other.php.punctuation.quoted.source.string.string-contents.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "index", + "t": "block.double.embedded.index.meta.other.php.quoted.source.string.string-contents.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "]", + "t": "array.block.double.embedded.end.meta.php.punctuation.quoted.section.source.string.string-contents", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.string rgb(206, 145, 120)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.string rgb(163, 21, 21)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": " ", + "t": "block.double.embedded.meta.php.quoted.source.string.string-contents", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.string rgb(206, 145, 120)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.string rgb(163, 21, 21)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "\"", + "t": "block.definition.double.embedded.end.meta.php.punctuation.quoted.source.string", "r": { "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.string rgb(206, 145, 120)", "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.string rgb(163, 21, 21)", @@ -2575,7 +3136,7 @@ }, { "c": ")", - "t": "delimiter.parenthesis.php", + "t": "block.embedded.meta.php.source", "r": { "dark_plus": ".vs-dark .token rgb(212, 212, 212)", "light_plus": ".vs .token rgb(0, 0, 0)", @@ -2586,7 +3147,7 @@ }, { "c": ";", - "t": "delimiter.php", + "t": "block.embedded.expression.meta.php.punctuation.source.terminator", "r": { "dark_plus": ".vs-dark .token rgb(212, 212, 212)", "light_plus": ".vs .token rgb(0, 0, 0)", @@ -2597,7 +3158,7 @@ }, { "c": "\t\t", - "t": "", + "t": "block.embedded.meta.php.source", "r": { "dark_plus": ".vs-dark .token rgb(212, 212, 212)", "light_plus": ".vs .token rgb(0, 0, 0)", @@ -2607,8 +3168,8 @@ } }, { - "c": "$starting_point", - "t": "php.variable", + "c": "$", + "t": "block.definition.embedded.meta.other.php.punctuation.source.variable", "r": { "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", @@ -2618,8 +3179,30 @@ } }, { - "c": "++;", - "t": "delimiter.php", + "c": "starting_point", + "t": "block.embedded.meta.other.php.source.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "++", + "t": "block.embedded.increment-decrement.keyword.meta.operator.php.source", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.keyword.operator rgb(212, 212, 212)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.keyword.operator rgb(0, 0, 0)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.keyword.operator rgb(212, 212, 212)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.keyword.operator rgb(0, 0, 0)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.keyword.operator rgb(212, 212, 212)" + } + }, + { + "c": ";", + "t": "block.embedded.expression.meta.php.punctuation.source.terminator", "r": { "dark_plus": ".vs-dark .token rgb(212, 212, 212)", "light_plus": ".vs .token rgb(0, 0, 0)", @@ -2630,7 +3213,7 @@ }, { "c": "\t", - "t": "", + "t": "block.embedded.meta.php.source", "r": { "dark_plus": ".vs-dark .token rgb(212, 212, 212)", "light_plus": ".vs .token rgb(0, 0, 0)", @@ -2641,7 +3224,7 @@ }, { "c": "}", - "t": "bracket.delimiter.php", + "t": "block.embedded.end.meta.php.punctuation.scope.section.source", "r": { "dark_plus": ".vs-dark .token rgb(212, 212, 212)", "light_plus": ".vs .token rgb(0, 0, 0)", @@ -2651,8 +3234,19 @@ } }, { - "c": "?>", - "t": "metatag.php", + "c": "?", + "t": "block.embedded.end.meta.metatag.php.punctuation.section.source", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.metatag.php rgb(86, 156, 214)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.metatag.php rgb(128, 0, 0)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.metatag.php rgb(86, 156, 214)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.metatag.php rgb(128, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": ">", + "t": "block.embedded.end.meta.metatag.php.punctuation.section", "r": { "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.metatag.php rgb(86, 156, 214)", "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.metatag.php rgb(128, 0, 0)", @@ -2663,7 +3257,7 @@ }, { "c": "", - "t": "definition.end.html.meta.punctuation.tag", + "t": "any.definition.html.meta.punctuation.structure.tag", "r": { "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.meta.tag rgb(128, 128, 128)", "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.meta.tag rgb(128, 0, 0)", @@ -2696,7 +3290,7 @@ }, { "c": "", - "t": "definition.end.html.meta.punctuation.tag", + "t": "any.definition.html.meta.punctuation.structure.tag", "r": { "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.meta.tag rgb(128, 128, 128)", "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.meta.tag rgb(128, 0, 0)", diff --git a/src/vs/editor/editor.main.ts b/src/vs/editor/editor.main.ts index f89c8cee7a9..241982bf35b 100644 --- a/src/vs/editor/editor.main.ts +++ b/src/vs/editor/editor.main.ts @@ -12,4 +12,5 @@ import 'vs/editor/contrib/quickOpen/browser/gotoLine.contribution'; import 'vs/editor/contrib/quickOpen/browser/quickCommand.contribution'; import 'vs/languages/languages.main'; import 'vs/languages/typescript/common/typescript.contribution'; +import 'vs/languages/php/common/php.contribution'; import 'vs/languages/json/common/json.contribution'; diff --git a/src/vs/languages/languages.main.ts b/src/vs/languages/languages.main.ts index 65834ae83fd..4f184f5eab9 100644 --- a/src/vs/languages/languages.main.ts +++ b/src/vs/languages/languages.main.ts @@ -9,7 +9,6 @@ import 'vs/languages/css/common/css.contribution'; import 'vs/languages/handlebars/common/handlebars.contribution'; import 'vs/languages/html/common/html.contribution'; import 'vs/languages/markdown/common/markdown.contribution'; -import 'vs/languages/php/common/php.contribution'; import 'vs/languages/razor/common/razor.contribution'; import 'vs/languages/less/common/less.contribution'; import 'vs/languages/sass/common/sass.contribution'; From 224bbb8b453715395ec5e7b7a6dc546f7eb2c08b Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 10 May 2016 14:38:51 +0200 Subject: [PATCH 120/297] run the actual ai module inside the shared process such that it cannot tamper with the main process, fixes #1000 --- src/vs/base/parts/ai/node/ai.app.ts | 52 ++++++++++++ src/vs/base/parts/ai/node/ai.ipc.ts | 16 ++++ src/vs/base/parts/ai/node/ai.ts | 53 ++++++++++++ src/vs/base/{ => parts/ai}/node/aiAdapter.ts | 27 ++---- .../test/node/aiAdapter/aiAdapter.test.ts | 9 +- src/vs/code/node/sharedProcessMain.ts | 2 + .../telemetry/node/appInsightsAppender.ts | 53 +++--------- .../telemetry/node/commonProperties.ts | 1 - .../test/node/appInsightsAppender.test.ts | 82 ------------------- src/vs/workbench/electron-browser/shell.ts | 4 +- .../debug/electron-browser/debugService.ts | 23 +++--- .../parts/debug/node/rawDebugSession.ts | 4 +- 12 files changed, 161 insertions(+), 165 deletions(-) create mode 100644 src/vs/base/parts/ai/node/ai.app.ts create mode 100644 src/vs/base/parts/ai/node/ai.ipc.ts create mode 100644 src/vs/base/parts/ai/node/ai.ts rename src/vs/base/{ => parts/ai}/node/aiAdapter.ts (91%) delete mode 100644 src/vs/platform/telemetry/test/node/appInsightsAppender.test.ts diff --git a/src/vs/base/parts/ai/node/ai.app.ts b/src/vs/base/parts/ai/node/ai.app.ts new file mode 100644 index 00000000000..c690ad3c087 --- /dev/null +++ b/src/vs/base/parts/ai/node/ai.app.ts @@ -0,0 +1,52 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import {TPromise} from 'vs/base/common/winjs.base'; +import {IServer} from 'vs/base/parts/ipc/common/ipc'; +import {AIAdapter} from './aiAdapter'; +import {IAIChannel} from './ai.ipc'; + +const adapter: { [handle: number]: AIAdapter } = Object.create(null); +let idPool = 0; + +export function registerAIChannel(server: IServer) { + server.registerChannel('ai', { + call(command: string, arg: any): TPromise { + switch (command) { + case 'create': { + let handle = idPool++; + let {key, eventPrefix, data} = arg; + adapter[handle] = new AIAdapter(eventPrefix, data, key); + return TPromise.as(handle); + } + case 'log': { + let {handle, eventName, data} = arg; + adapter[handle].log(eventName, data); + return TPromise.as(undefined); + } + case 'dispose': { + let {handle} = arg; + adapter[handle].dispose(); + delete adapter[handle]; + return TPromise.as(undefined); + } + } + } + }); +} + +// It is important to dispose the AI adapter properly because +// only then they flush remaining data. +process.on('SIGTERM', function () { + console.log('HERE'); + let promises: TPromise[] = []; + for (let handle in adapter) { + let ai = adapter[handle]; + promises.push(ai.dispose()); + } + TPromise.join(promises).then(_ => process.exit(0)); +}); diff --git a/src/vs/base/parts/ai/node/ai.ipc.ts b/src/vs/base/parts/ai/node/ai.ipc.ts new file mode 100644 index 00000000000..639c625ccda --- /dev/null +++ b/src/vs/base/parts/ai/node/ai.ipc.ts @@ -0,0 +1,16 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import {TPromise} from 'vs/base/common/winjs.base'; +import {IChannel} from 'vs/base/parts/ipc/common/ipc'; + +export interface IAIChannel extends IChannel { + call(command: 'create', data: { key: string; eventPrefix: string; data: any; }): TPromise; + call(command: 'log', data: { handle: number; eventName: string; data: any; }): TPromise; + call(command: 'dispose', data: { handle: number; }): TPromise; + call(command: string, arg: any): TPromise; +} diff --git a/src/vs/base/parts/ai/node/ai.ts b/src/vs/base/parts/ai/node/ai.ts new file mode 100644 index 00000000000..ad0a74ebaa8 --- /dev/null +++ b/src/vs/base/parts/ai/node/ai.ts @@ -0,0 +1,53 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import {IAIChannel} from './ai.ipc'; +import {TPromise} from 'vs/base/common/winjs.base'; +import {connect} from 'vs/base/parts/ipc/node/ipc.net'; + +export interface IAIAdapter { + log(eventName: string, data?: any): void; + dispose(): void; +} + +export function createAIAdapter(key: string, eventPrefix: string, data: { [key: string]: any }): IAIAdapter { + + let beforeReadyMessages: { type: string; args: any }[] = []; + let handle: number = undefined; + let channel: IAIChannel = { + call(type: string, args: any): TPromise { + beforeReadyMessages.push({ type, args }); + return TPromise.as(void 0); + } + }; + + connect(process.env['VSCODE_SHARED_IPC_HOOK']).then(client => client.getChannel('ai')).then(actualChannel => { + + return actualChannel.call('create', { key, eventPrefix, data }).then(actualHandle => { + // channel has been created, store handle etc, + // and flush all early messages + handle = actualHandle; + channel = actualChannel; + for (let m of beforeReadyMessages) { + let {type, args} = m; + args.handle = handle; + channel.call(type, args); + } + beforeReadyMessages.length = 0; + }); + }); + + return { + log(eventName: string, data?: any) { + channel.call('log', { handle, eventName, data }); + }, + dispose() { + channel.call('dispose', { handle }); + } + }; + +} diff --git a/src/vs/base/node/aiAdapter.ts b/src/vs/base/parts/ai/node/aiAdapter.ts similarity index 91% rename from src/vs/base/node/aiAdapter.ts rename to src/vs/base/parts/ai/node/aiAdapter.ts index 495b942601d..2d1615678c5 100644 --- a/src/vs/base/node/aiAdapter.ts +++ b/src/vs/base/parts/ai/node/aiAdapter.ts @@ -4,16 +4,10 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; +import * as appInsights from 'applicationinsights'; import {isObject} from 'vs/base/common/types'; import {safeStringify, mixin} from 'vs/base/common/objects'; import {TPromise} from 'vs/base/common/winjs.base'; -import * as appInsights from 'applicationinsights'; - -export interface IAIAdapter { - log(eventName: string, data?: any): void; - logException(exception: any): void; - dispose(): void; -} namespace AI { @@ -54,7 +48,7 @@ interface Measurements { [key: string]: number; } -export class AIAdapter implements IAIAdapter { +export class AIAdapter { private _aiClient: typeof appInsights.client; @@ -150,17 +144,14 @@ export class AIAdapter implements IAIAdapter { }); } - public logException(exception: any): void { + public dispose(): TPromise { if (this._aiClient) { - this._aiClient.trackException(exception); - } - } - - public dispose(): void { - if (this._aiClient) { - this._aiClient.sendPendingData(() => { - // all data flushed - this._aiClient = undefined; + return new TPromise(resolve => { + this._aiClient.sendPendingData(() => { + // all data flushed + this._aiClient = undefined; + resolve(void 0); + }); }); } } diff --git a/src/vs/base/test/node/aiAdapter/aiAdapter.test.ts b/src/vs/base/test/node/aiAdapter/aiAdapter.test.ts index 291871b2c36..bbf1b19ce74 100644 --- a/src/vs/base/test/node/aiAdapter/aiAdapter.test.ts +++ b/src/vs/base/test/node/aiAdapter/aiAdapter.test.ts @@ -6,7 +6,7 @@ import * as assert from 'assert'; import {TPromise} from 'vs/base/common/winjs.base'; -import {AIAdapter} from 'vs/base/node/aiAdapter'; +import {AIAdapter} from 'vs/base/parts/ai/node/aiAdapter'; interface IAppInsightsEvent { eventName: string; @@ -73,13 +73,6 @@ suite('AIAdapter', () => { assert.equal(first.measurements['third'], 1); }); - test('Track UnhandledError as exception and events', () => { - var sampleError = new Error('test'); - - adapter.logException(sampleError); - assert.equal(appInsightsMock.exceptions.length, 1); - }); - test('property limits', () => { var reallyLongPropertyName = 'abcdefghijklmnopqrstuvwxyz'; for (var i = 0; i < 6; i++) { diff --git a/src/vs/code/node/sharedProcessMain.ts b/src/vs/code/node/sharedProcessMain.ts index 67d7c1a4c9a..85c7ccc35b3 100644 --- a/src/vs/code/node/sharedProcessMain.ts +++ b/src/vs/code/node/sharedProcessMain.ts @@ -7,6 +7,7 @@ import * as fs from 'fs'; import * as platform from 'vs/base/common/platform'; import { serve, Server, connect } from 'vs/base/parts/ipc/node/ipc.net'; import { TPromise } from 'vs/base/common/winjs.base'; +import { registerAIChannel } from 'vs/base/parts/ai/node/ai.app'; import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService'; @@ -52,6 +53,7 @@ function main(server: Server): void { const extensionManagementService = accessor.get(IExtensionManagementService); const channel = new ExtensionManagementChannel(extensionManagementService); server.registerChannel('extensions', channel); + registerAIChannel(server); // eventually clean up old extensions setTimeout(() => (extensionManagementService as ExtensionManagementService).removeDeprecatedExtensions(), 5000); diff --git a/src/vs/platform/telemetry/node/appInsightsAppender.ts b/src/vs/platform/telemetry/node/appInsightsAppender.ts index bc44e6bd618..a6e0b58d334 100644 --- a/src/vs/platform/telemetry/node/appInsightsAppender.ts +++ b/src/vs/platform/telemetry/node/appInsightsAppender.ts @@ -4,51 +4,20 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; +import {IEnvironment} from 'vs/platform/workspace/common/workspace'; import {ITelemetryAppender} from 'vs/platform/telemetry/common/telemetry'; -import {AIAdapter, IAIAdapter} from 'vs/base/node/aiAdapter'; +import {createAIAdapter} from 'vs/base/parts/ai/node/ai'; -export class AppInsightsAppender implements ITelemetryAppender { +const eventPrefix = 'monacoworkbench'; - private static EVENT_NAME_PREFIX: string = 'monacoworkbench'; - - private appInsights: IAIAdapter; - private appInsightsVortex: IAIAdapter; - - constructor(config: { key: string; asimovKey: string }, _testing_client?: IAIAdapter) { - let {key, asimovKey} = config; - if (_testing_client) { - // for test - this.appInsights = _testing_client; - if (asimovKey) { - this.appInsightsVortex = _testing_client; - } - } else { - if (key) { - this.appInsights = new AIAdapter(AppInsightsAppender.EVENT_NAME_PREFIX, undefined, key); - } - if (asimovKey) { - this.appInsightsVortex = new AIAdapter(AppInsightsAppender.EVENT_NAME_PREFIX, undefined, asimovKey); - } - } +export function createAppender(env: IEnvironment): ITelemetryAppender[]{ + const result: ITelemetryAppender[] = []; + let {key, asimovKey} = env.aiConfig; + if (key) { + result.push(createAIAdapter(key, eventPrefix, undefined)); } - - public log(eventName: string, data: any = Object.create(null)): void { - if (this.appInsights) { - this.appInsights.log(eventName, data); - } - if (this.appInsightsVortex) { - this.appInsightsVortex.log(eventName, data); - } - } - - public dispose(): void { - if (this.appInsights) { - this.appInsights.dispose(); - } - if (this.appInsightsVortex) { - this.appInsightsVortex.dispose(); - } - this.appInsights = null; - this.appInsightsVortex = null; + if (asimovKey) { + result.push(createAIAdapter(asimovKey, eventPrefix, undefined)); } + return result; } diff --git a/src/vs/platform/telemetry/node/commonProperties.ts b/src/vs/platform/telemetry/node/commonProperties.ts index e4adcd89d29..c303ea92032 100644 --- a/src/vs/platform/telemetry/node/commonProperties.ts +++ b/src/vs/platform/telemetry/node/commonProperties.ts @@ -47,7 +47,6 @@ export function resolveCommonProperties(storageService: IStorageService, context result['common.lastSessionDate'] = lastSessionDate; result['common.isNewSession'] = !lastSessionDate ? 1 : 0; - // dynamic properties which value differs on each call let seq = 0; const startTime = Date.now(); diff --git a/src/vs/platform/telemetry/test/node/appInsightsAppender.test.ts b/src/vs/platform/telemetry/test/node/appInsightsAppender.test.ts deleted file mode 100644 index 7f4f3074a66..00000000000 --- a/src/vs/platform/telemetry/test/node/appInsightsAppender.test.ts +++ /dev/null @@ -1,82 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -'use strict'; - -import * as assert from 'assert'; -import {IAIAdapter} from 'vs/base/node/aiAdapter'; -import {AppInsightsAppender} from 'vs/platform/telemetry/node/appInsightsAppender'; - -interface IAppInsightsEvent { - eventName: string; - data: any; -} - -class AIAdapterMock implements IAIAdapter { - - public events: IAppInsightsEvent[] = []; - public IsTrackingPageView: boolean = false; - public exceptions: any[] = []; - - constructor(private prefix: string) { - } - - public log(eventName: string, data?: any): void { - this.events.push({ - eventName: this.prefix + '/' + eventName, - data: data - }); - } - - public logException(exception: any): void { - this.exceptions.push(exception); - } - - public dispose(): void { - } -} - -suite('Telemetry - AppInsightsTelemetryAppender', () => { - var appInsightsMock: AIAdapterMock; - var appender: AppInsightsAppender; - - setup(() => { - appInsightsMock = new AIAdapterMock('testPrefix'); - appender = new AppInsightsAppender({ key: '123', asimovKey: undefined }, appInsightsMock); - }); - - teardown(() => { - appender.dispose(); - }); - - test('Simple event', () => { - appender.log('testEvent'); - assert.equal(appInsightsMock.events.length, 1); - assert.equal(appInsightsMock.events[0].eventName, 'testPrefix/testEvent'); - }); - - test('Event with data', () => { - appender.log('testEvent', { - title: 'some title', - width: 100, - height: 200 - }); - assert.equal(appInsightsMock.events.length, 1); - assert.equal(appInsightsMock.events[0].eventName, 'testPrefix/testEvent'); - - assert.equal(appInsightsMock.events[0].data['title'], 'some title'); - assert.equal(appInsightsMock.events[0].data['width'], 100); - assert.equal(appInsightsMock.events[0].data['height'], 200); - }); - - test('Test asimov', () => { - appender = new AppInsightsAppender({ key: '123', asimovKey: 'AIF-123' }, appInsightsMock); - appender.log('testEvent'); - assert.equal(appInsightsMock.events.length, 2); - assert.equal(appInsightsMock.events[0].eventName, 'testPrefix/testEvent'); - - // test vortex - assert.equal(appInsightsMock.events[1].eventName, 'testPrefix/testEvent'); - }); -}); \ No newline at end of file diff --git a/src/vs/workbench/electron-browser/shell.ts b/src/vs/workbench/electron-browser/shell.ts index ca2802b3c91..f70ef0a6777 100644 --- a/src/vs/workbench/electron-browser/shell.ts +++ b/src/vs/workbench/electron-browser/shell.ts @@ -21,7 +21,7 @@ import {Workbench} from 'vs/workbench/browser/workbench'; import {Storage, inMemoryLocalStorageInstance} from 'vs/workbench/common/storage'; import {ITelemetryService, NullTelemetryService} from 'vs/platform/telemetry/common/telemetry'; import {TelemetryService} from 'vs/platform/telemetry/browser/telemetryService'; -import {AppInsightsAppender} from 'vs/platform/telemetry/node/appInsightsAppender'; +import {createAppender} from 'vs/platform/telemetry/node/appInsightsAppender'; import {resolveCommonProperties} from 'vs/platform/telemetry/node/commonProperties'; import {ElectronIntegration} from 'vs/workbench/electron-browser/integration'; import {Update} from 'vs/workbench/electron-browser/update'; @@ -206,7 +206,7 @@ export class WorkbenchShell { if (this.configuration.env.isBuilt && !this.configuration.env.extensionDevelopmentPath && !!this.configuration.env.enableTelemetry) { this.telemetryService = new TelemetryService({ - appender: [new AppInsightsAppender(this.configuration.env.aiConfig)], + appender: createAppender(this.configuration.env), commonProperties: resolveCommonProperties(this.storageService, this.contextService), piiPaths: [this.configuration.env.appRoot, this.configuration.env.userExtensionsHome] }, this.configurationService); diff --git a/src/vs/workbench/parts/debug/electron-browser/debugService.ts b/src/vs/workbench/parts/debug/electron-browser/debugService.ts index 45eadde5995..3cf48ee256d 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugService.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugService.ts @@ -16,7 +16,7 @@ import errors = require('vs/base/common/errors'); import severity from 'vs/base/common/severity'; import { TPromise } from 'vs/base/common/winjs.base'; import aria = require('vs/base/browser/ui/aria/aria'); -import { AIAdapter } from 'vs/base/node/aiAdapter'; +import { IAIAdapter, createAIAdapter } from 'vs/base/parts/ai/node/ai'; import editorbrowser = require('vs/editor/browser/editorBrowser'); import { IKeybindingService, IKeybindingContextKey } from 'vs/platform/keybinding/common/keybindingService'; import {IMarkerService} from 'vs/platform/markers/common/markers'; @@ -67,7 +67,7 @@ export class DebugService implements debug.IDebugService { private viewModel: viewmodel.ViewModel; private configurationManager: ConfigurationManager; private debugStringEditorInputs: DebugStringEditorInput[]; - private telemetryAdapter: AIAdapter; + private telemetryAdapter: IAIAdapter; private lastTaskEvent: TaskEvent; private toDispose: lifecycle.IDisposable[]; private toDisposeOnSessionEnd: lifecycle.IDisposable[]; @@ -542,14 +542,17 @@ export class DebugService implements debug.IDebugService { private doCreateSession(configuration: debug.IConfig, changeViewState: boolean): TPromise { this.setStateAndEmit(debug.State.Initializing); - this.telemetryAdapter = new AIAdapter(this.configurationManager.adapter.type, () => { - return this.telemetryService.getTelemetryInfo().then(info => { - const telemetryInfo: { [key: string]: string } = Object.create(null); - telemetryInfo['common.vscodemachineid'] = info.machineId; - telemetryInfo['common.vscodesessionid'] = info.sessionId; - return telemetryInfo; - }); - }, this.configurationManager.adapter.aiKey); + + this.telemetryService.getTelemetryInfo().then(info => { + const telemetryInfo: { [key: string]: string } = Object.create(null); + telemetryInfo['common.vscodemachineid'] = info.machineId; + telemetryInfo['common.vscodesessionid'] = info.sessionId; + return telemetryInfo; + }).then(data => { + let {aiKey, type} = this.configurationManager.adapter; + this.telemetryAdapter = createAIAdapter(aiKey, type, data); + }); + this.session = this.instantiationService.createInstance(session.RawDebugSession, configuration.debugServer, this.configurationManager.adapter, this.telemetryAdapter); this.registerSessionListeners(); diff --git a/src/vs/workbench/parts/debug/node/rawDebugSession.ts b/src/vs/workbench/parts/debug/node/rawDebugSession.ts index d792314962b..bd37c05f9f0 100644 --- a/src/vs/workbench/parts/debug/node/rawDebugSession.ts +++ b/src/vs/workbench/parts/debug/node/rawDebugSession.ts @@ -13,7 +13,7 @@ import { Action } from 'vs/base/common/actions'; import errors = require('vs/base/common/errors'); import { TPromise } from 'vs/base/common/winjs.base'; import severity from 'vs/base/common/severity'; -import { AIAdapter } from 'vs/base/node/aiAdapter'; +import { IAIAdapter } from 'vs/base/parts/ai/node/ai'; import stdfork = require('vs/base/node/stdFork'); import { IMessageService, CloseAction } from 'vs/platform/message/common/message'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; @@ -66,7 +66,7 @@ export class RawDebugSession extends v8.V8Protocol implements debug.IRawDebugSes constructor( private debugServerPort: number, private adapter: Adapter, - private telemtryAdapter: AIAdapter, + private telemtryAdapter: IAIAdapter, @IMessageService private messageService: IMessageService, @ITelemetryService private telemetryService: ITelemetryService, @IOutputService private outputService: IOutputService From 39c835a56c36da5998e8f55f9f74985c42182b83 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Tue, 10 May 2016 12:53:38 +0200 Subject: [PATCH 121/297] fixes #5981: [json] accept empty keybindings.json file --- extensions/json/server/src/server.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/extensions/json/server/src/server.ts b/extensions/json/server/src/server.ts index 3005cd1c00f..6fa750dc0c4 100644 --- a/extensions/json/server/src/server.ts +++ b/extensions/json/server/src/server.ts @@ -210,6 +210,12 @@ function updateConfiguration() { function validateTextDocument(textDocument: ITextDocument): void { + if (textDocument.getText().length === 0) { + // ignore empty documents + connection.sendDiagnostics({ uri: textDocument.uri, diagnostics: [] }); + return; + } + let jsonDocument = getJSONDocument(textDocument); jsonSchemaService.getSchemaForResource(textDocument.uri, jsonDocument).then(schema => { if (schema) { From 083c36c60908006f7e19e4e89890a4345fb2245b Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Tue, 10 May 2016 15:10:13 +0200 Subject: [PATCH 122/297] fixes #5965: [less] syntax failure when identifier starts with a number --- src/vs/languages/css/common/parser/cssScanner.ts | 2 +- src/vs/languages/css/test/common/scanner.test.ts | 2 +- src/vs/languages/less/test/common/parser.test.ts | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/vs/languages/css/common/parser/cssScanner.ts b/src/vs/languages/css/common/parser/cssScanner.ts index c2ee8abeda8..461ad682dc6 100644 --- a/src/vs/languages/css/common/parser/cssScanner.ts +++ b/src/vs/languages/css/common/parser/cssScanner.ts @@ -296,7 +296,7 @@ export class Scanner { // at-keyword if (this.stream.advanceIfChar(_ATS)) { content = [ '@' ]; - if (this.ident(content)) { + if (this._name(content)) { let keywordText = content.join(''); if (keywordText === '@charset') { return this.finishToken(offset, TokenType.Charset, keywordText); diff --git a/src/vs/languages/css/test/common/scanner.test.ts b/src/vs/languages/css/test/common/scanner.test.ts index b4664664950..56058e969b8 100644 --- a/src/vs/languages/css/test/common/scanner.test.ts +++ b/src/vs/languages/css/test/common/scanner.test.ts @@ -76,7 +76,7 @@ suite('CSS - Scanner', () => { assertSingleToken(scanner, '@import', 7, 0, '@import', Scanner.TokenType.AtKeyword); assertSingleToken(scanner, '@importttt', 10, 0, '@importttt', Scanner.TokenType.AtKeyword); assertSingleToken(scanner, '@imp', 4, 0, '@imp', Scanner.TokenType.AtKeyword); - assertSingleToken(scanner, '@5', 1, 0, '@', Scanner.TokenType.Delim); + assertSingleToken(scanner, '@5', 2, 0, '@5', Scanner.TokenType.AtKeyword); assertSingleToken(scanner, '@media', 6, 0, '@media', Scanner.TokenType.AtKeyword); assertSingleToken(scanner, '@page', 5, 0, '@page', Scanner.TokenType.AtKeyword); assertSingleToken(scanner, '@charset', 8, 0, '@charset', Scanner.TokenType.Charset); diff --git a/src/vs/languages/less/test/common/parser.test.ts b/src/vs/languages/less/test/common/parser.test.ts index 1040b954583..0a75954bbf3 100644 --- a/src/vs/languages/less/test/common/parser.test.ts +++ b/src/vs/languages/less/test/common/parser.test.ts @@ -33,6 +33,7 @@ suite('LESS - LESS Parser', () => { assertNode('@-co42lor', parser, parser._parseVariable.bind(parser)); assertNode('@@foo', parser, parser._parseVariable.bind(parser)); assertNode('@@@foo', parser, parser._parseVariable.bind(parser)); + assertNode('@12ooo', parser, parser._parseVariable.bind(parser)); assertNoNode('@ @foo', parser, parser._parseFunction.bind(parser)); assertNoNode('@-@foo', parser, parser._parseFunction.bind(parser)); }); From 83a7759f9ba4befd3ec08838b8f0cea4eb21e5ee Mon Sep 17 00:00:00 2001 From: isidor Date: Tue, 10 May 2016 15:17:00 +0200 Subject: [PATCH 123/297] debug: expose vscode.debugStart in API fixes #3789 --- src/vs/workbench/api/node/extHostApiCommands.ts | 9 +++++++++ .../parts/debug/browser/debugActionItems.ts | 13 +++++++++---- .../electron-browser/debug.contribution.ts | 17 ++++++++++++++++- .../debug/electron-browser/debugActions.ts | 11 ++++++----- 4 files changed, 40 insertions(+), 10 deletions(-) diff --git a/src/vs/workbench/api/node/extHostApiCommands.ts b/src/vs/workbench/api/node/extHostApiCommands.ts index c56ddbb3733..d4bf26e343e 100644 --- a/src/vs/workbench/api/node/extHostApiCommands.ts +++ b/src/vs/workbench/api/node/extHostApiCommands.ts @@ -188,6 +188,15 @@ class ExtHostApiCommands { { name: 'newWindow', description: '(optional) Wether to open the folder in a new window or the same. Defaults to opening in the same window.', constraint: value => value === void 0 || typeof value === 'boolean' } ] }); + + this._register('vscode.startDebug', (configurationName?: string) => { + return this._commands.executeCommand('_workbench.startDebug', configurationName); + }, { + description: 'Start a debugging session.', + args: [ + { name: 'configurationName', description: '(optional) Name of the debug configuration from \'launch.json\' to use.' } + ] + }); } // --- command impl diff --git a/src/vs/workbench/parts/debug/browser/debugActionItems.ts b/src/vs/workbench/parts/debug/browser/debugActionItems.ts index 5ff87faed7e..ae050357f6f 100644 --- a/src/vs/workbench/parts/debug/browser/debugActionItems.ts +++ b/src/vs/workbench/parts/debug/browser/debugActionItems.ts @@ -40,14 +40,17 @@ export class SelectConfigActionItem extends BaseActionItem { this.select.disabled = state !== State.Inactive; })); this.toDispose.push(configurationService.onDidUpdateConfiguration(e => { - this.setOptions().done(null, errors.onUnexpectedError); + this.setOptions(true).done(null, errors.onUnexpectedError); + })); + this.toDispose.push(this.debugService.getConfigurationManager().onDidConfigurationChange(name => { + this.setOptions(false).done(null, errors.onUnexpectedError); })); } public render(container: HTMLElement): void { dom.addClass(container, 'select-container'); container.appendChild(this.select); - this.setOptions().done(null, errors.onUnexpectedError); + this.setOptions(true).done(null, errors.onUnexpectedError); } public focus(): void { @@ -62,7 +65,7 @@ export class SelectConfigActionItem extends BaseActionItem { } } - private setOptions(): TPromise { + private setOptions(changeDebugConfiguration: boolean): TPromise { let previousSelectedIndex = this.select.selectedIndex; this.select.options.length = 0; @@ -91,7 +94,9 @@ export class SelectConfigActionItem extends BaseActionItem { previousSelectedIndex = 0; } this.select.selectedIndex = previousSelectedIndex; - return this.actionRunner.run(this._action, configurations[previousSelectedIndex].name); + if (changeDebugConfiguration) { + return this.actionRunner.run(this._action, configurations[previousSelectedIndex].name); + } } }); } diff --git a/src/vs/workbench/parts/debug/electron-browser/debug.contribution.ts b/src/vs/workbench/parts/debug/electron-browser/debug.contribution.ts index 83889ef0cd7..7fc5dd4edb1 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debug.contribution.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debug.contribution.ts @@ -6,15 +6,18 @@ import 'vs/css!../browser/media/debug.contribution'; import 'vs/css!../browser/media/debugHover'; import nls = require('vs/nls'); +import { TPromise } from 'vs/base/common/winjs.base'; import { KeyMod, KeyCode } from 'vs/base/common/keyCodes'; +import errors = require('vs/base/common/errors'); import editorcommon = require('vs/editor/common/editorCommon'); import { CommonEditorRegistry, ContextKey, EditorActionDescriptor } from 'vs/editor/common/editorCommonExtensions'; +import { EditorBrowserRegistry } from 'vs/editor/browser/editorBrowserExtensions'; import { SyncActionDescriptor } from 'vs/platform/actions/common/actions'; import platform = require('vs/platform/platform'); import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { KbExpr, IKeybindings } from 'vs/platform/keybinding/common/keybindingService'; -import { EditorBrowserRegistry } from 'vs/editor/browser/editorBrowserExtensions'; +import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import wbaregistry = require('vs/workbench/common/actionRegistry'); import viewlet = require('vs/workbench/browser/viewlet'); import panel = require('vs/workbench/browser/panel'); @@ -113,5 +116,17 @@ registry.registerWorkbenchAction(new SyncActionDescriptor(dbgactions.AddFunction registry.registerWorkbenchAction(new SyncActionDescriptor(dbgactions.ReapplyBreakpointsAction, dbgactions.ReapplyBreakpointsAction.ID, dbgactions.ReapplyBreakpointsAction.LABEL), 'Debug: Reapply All Breakpoints', debugCategory); registry.registerWorkbenchAction(new SyncActionDescriptor(dbgactions.RunAction, dbgactions.RunAction.ID, dbgactions.RunAction.LABEL, { primary: KeyMod.CtrlCmd | KeyCode.F5 }, KbExpr.not(debug.CONTEXT_IN_DEBUG_MODE)), 'Debug: Start Without Debugging', debugCategory); +KeybindingsRegistry.registerCommandDesc({ + id: '_workbench.startDebug', + weight: KeybindingsRegistry.WEIGHT.workbenchContrib(0), + handler(accessor: ServicesAccessor, configurationName: string) { + const debugService = accessor.get(debug.IDebugService); + (configurationName ? debugService.getConfigurationManager().setConfiguration(configurationName) : TPromise.as(null)) + .done(() => debugService.createSession(false), errors.onUnexpectedError); + }, + when: KbExpr.not(debug.CONTEXT_IN_DEBUG_MODE), + primary: undefined +}); + // register service registerSingleton(IDebugService, service.DebugService); diff --git a/src/vs/workbench/parts/debug/electron-browser/debugActions.ts b/src/vs/workbench/parts/debug/electron-browser/debugActions.ts index a7d4dcc4351..f3acc177c32 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugActions.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugActions.ts @@ -27,15 +27,16 @@ import IDebugService = debug.IDebugService; export class AbstractDebugAction extends actions.Action { - protected debugService: IDebugService; - private keybindingService: IKeybindingService; protected toDispose: lifecycle.IDisposable[]; private keybinding: string; - constructor(id: string, label: string, cssClass: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) { + constructor( + id: string, label: string, cssClass: string, + @IDebugService protected debugService: IDebugService, + @IKeybindingService protected keybindingService: IKeybindingService + ) { super(id, label, cssClass, false); this.debugService = debugService; - this.keybindingService = keybindingService; this.toDispose = []; this.toDispose.push(this.debugService.onDidChangeState((state) => this.updateEnablement(state))); @@ -119,7 +120,7 @@ export class StartDebugAction extends AbstractDebugAction { } public run(): TPromise { - return this.debugService.createSession(false); + return this.keybindingService.executeCommand('_workbench.startDebug'); } protected isEnabled(state: debug.State): boolean { From d894008ecc33feeac43bfb70f5ee3acd34dcdc3b Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 10 May 2016 15:20:07 +0200 Subject: [PATCH 124/297] dispose telemetry service and appenders on shutdown --- src/vs/base/common/lifecycle.ts | 12 ++++++++-- .../telemetry/browser/telemetryService.ts | 3 --- .../test/node/telemetryService.test.ts | 2 +- src/vs/workbench/electron-browser/shell.ts | 24 +++++++++++-------- 4 files changed, 25 insertions(+), 16 deletions(-) diff --git a/src/vs/base/common/lifecycle.ts b/src/vs/base/common/lifecycle.ts index 74042437db5..12268356fde 100644 --- a/src/vs/base/common/lifecycle.ts +++ b/src/vs/base/common/lifecycle.ts @@ -83,7 +83,15 @@ export abstract class Disposable implements IDisposable { export class Disposables extends Disposable { - public add(disposable: IDisposable): void { - this._register(disposable); + public add(e: T): T; + public add(...elements: IDisposable[]): void; + public add(arg: T | T[]): T { + if (!Array.isArray(arg)) { + return this._register(arg); + } else { + for (let element of arg) { + return this._register(element); + } + } } } diff --git a/src/vs/platform/telemetry/browser/telemetryService.ts b/src/vs/platform/telemetry/browser/telemetryService.ts index 16b52fb6ff4..af92593b8cb 100644 --- a/src/vs/platform/telemetry/browser/telemetryService.ts +++ b/src/vs/platform/telemetry/browser/telemetryService.ts @@ -137,9 +137,6 @@ export class TelemetryService implements ITelemetryService { public dispose(): void { this._disposables = dispose(this._disposables); - for (let appender of this._configuration.appender) { - appender.dispose(); - } } public timedPublicLog(name: string, data?: any): ITimerEvent { diff --git a/src/vs/platform/telemetry/test/node/telemetryService.test.ts b/src/vs/platform/telemetry/test/node/telemetryService.test.ts index a78b2b43f6d..7613aaeb240 100644 --- a/src/vs/platform/telemetry/test/node/telemetryService.test.ts +++ b/src/vs/platform/telemetry/test/node/telemetryService.test.ts @@ -91,7 +91,7 @@ suite('TelemetryService', () => { assert.equal(testAppender.getEventsCount(), 1); service.dispose(); - assert.equal(testAppender.isDisposed, true); + assert.equal(!testAppender.isDisposed, true); }); })); diff --git a/src/vs/workbench/electron-browser/shell.ts b/src/vs/workbench/electron-browser/shell.ts index f70ef0a6777..67726ad8562 100644 --- a/src/vs/workbench/electron-browser/shell.ts +++ b/src/vs/workbench/electron-browser/shell.ts @@ -13,7 +13,7 @@ import * as platform from 'vs/base/common/platform'; import {Dimension, Builder, $} from 'vs/base/browser/builder'; import dom = require('vs/base/browser/dom'); import aria = require('vs/base/browser/ui/aria/aria'); -import {dispose, IDisposable} from 'vs/base/common/lifecycle'; +import {dispose, IDisposable, Disposables} from 'vs/base/common/lifecycle'; import errors = require('vs/base/common/errors'); import {ContextViewService} from 'vs/platform/contextview/browser/contextViewService'; import timer = require('vs/base/common/timer'); @@ -198,6 +198,7 @@ export class WorkbenchShell { private initServiceCollection(): [InstantiationService, ServiceCollection] { let serviceCollection = new ServiceCollection(); let instantiationService = new InstantiationService(serviceCollection, true); + let disposables = new Disposables(); this.windowService = new WindowService(); @@ -205,39 +206,41 @@ export class WorkbenchShell { this.storageService = new Storage(this.contextService, window.localStorage, disableWorkspaceStorage ? inMemoryLocalStorageInstance : window.localStorage); if (this.configuration.env.isBuilt && !this.configuration.env.extensionDevelopmentPath && !!this.configuration.env.enableTelemetry) { - this.telemetryService = new TelemetryService({ + const config = { appender: createAppender(this.configuration.env), commonProperties: resolveCommonProperties(this.storageService, this.contextService), piiPaths: [this.configuration.env.appRoot, this.configuration.env.userExtensionsHome] - }, this.configurationService); + }; + let telemetryService = new TelemetryService(config, this.configurationService); + this.telemetryService = telemetryService; + disposables.add(telemetryService, ...config.appender); } else { this.telemetryService = NullTelemetryService; } this.messageService = new MessageService(this.contextService, this.windowService, this.telemetryService); - let fileService = new FileService( + let fileService = disposables.add(new FileService( this.configurationService, this.eventService, this.contextService, this.messageService - ); + )); + let lifecycleService = new LifecycleService(this.messageService, this.windowService); - this.toUnbind.push(lifecycleService.onShutdown(() => fileService.dispose())); - + this.toUnbind.push(lifecycleService.onShutdown(() => disposables.dispose())); this.threadService = new MainThreadService(this.contextService, this.messageService, this.windowService, lifecycleService); let extensionService = new MainProcessExtensionService(this.contextService, this.threadService, this.messageService); this.contextViewService = new ContextViewService(this.container, this.telemetryService, this.messageService); - let requestService = new RequestService( + let requestService = disposables.add(new RequestService( this.contextService, this.configurationService, this.telemetryService - ); - this.toUnbind.push(lifecycleService.onShutdown(() => requestService.dispose())); + )); let markerService = new MainProcessMarkerService(this.threadService); @@ -248,6 +251,7 @@ export class WorkbenchShell { let untitledEditorService = instantiationService.createInstance(UntitledEditorService); this.themeService = new ThemeService(extensionService, this.windowService, this.storageService); + serviceCollection.set(ITelemetryService, this.telemetryService); serviceCollection.set(IEventService, this.eventService); serviceCollection.set(IRequestService, requestService); From 4a782befbb95b844f3b952a981e6b5fa19236c0a Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 10 May 2016 16:15:48 +0200 Subject: [PATCH 125/297] dbk - add pwd to test.sh --- scripts/test.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/test.sh b/scripts/test.sh index 81b742cfeeb..ee2abda0e4f 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -8,6 +8,8 @@ else ROOT=$(dirname $(dirname $(readlink -f $0))) fi +pwd + # Node modules test -d node_modules || ./scripts/npm.sh install From 4bc448702f27637cc0bb2f15b712745989fc6b52 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Tue, 10 May 2016 16:22:11 +0200 Subject: [PATCH 126/297] gulpfile-extensions: use relative source root --- build/gulpfile.extensions.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/build/gulpfile.extensions.js b/build/gulpfile.extensions.js index 0e78e41a569..41356d9bf7a 100644 --- a/build/gulpfile.extensions.js +++ b/build/gulpfile.extensions.js @@ -31,13 +31,12 @@ var languages = ['chs', 'cht', 'jpn', 'kor', 'deu', 'fra', 'esn', 'rus', 'ita']; var tasks = compilations.map(function(tsconfigFile) { var absolutePath = path.join(extensionsPath, tsconfigFile); - var absoluteDirname = path.dirname(absolutePath); var relativeDirname = path.dirname(tsconfigFile); var tsOptions = require(absolutePath).compilerOptions; tsOptions.verbose = !quiet; tsOptions.sourceMap = true; - tsOptions.sourceRoot = util.toFileUri(path.join(absoluteDirname, 'src')); + tsOptions.sourceRoot = '../src'; var name = relativeDirname.replace(/\//g, '-'); From b0bdf7b24ee9f5a334b1898aa1991357dbe6a2da Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 10 May 2016 16:36:22 +0200 Subject: [PATCH 127/297] better titles for file labels, fixes #6224 --- src/vs/base/browser/ui/filelabel/fileLabel.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vs/base/browser/ui/filelabel/fileLabel.ts b/src/vs/base/browser/ui/filelabel/fileLabel.ts index 0e03a75f14f..bff5fe30f1e 100644 --- a/src/vs/base/browser/ui/filelabel/fileLabel.ts +++ b/src/vs/base/browser/ui/filelabel/fileLabel.ts @@ -61,11 +61,12 @@ export class FileLabel { let parent = paths.dirname(this.path); if (parent && parent !== '.') { let pathLabel = getPathLabel(parent, this.basepath); - htmlContent.push(''); + htmlContent.push(''); htmlContent.push(pathLabel); htmlContent.push(''); } + this.domNode.title = this.path; this.domNode.innerHTML = htmlContent.join(''); } } From 174529be231534c978ff64145e6a56038edd6832 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 10 May 2016 16:40:12 +0200 Subject: [PATCH 128/297] add title for match, fixes #6224 --- src/vs/workbench/parts/search/browser/searchViewlet.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/parts/search/browser/searchViewlet.ts b/src/vs/workbench/parts/search/browser/searchViewlet.ts index 99582c9e59b..af02900fbda 100644 --- a/src/vs/workbench/parts/search/browser/searchViewlet.ts +++ b/src/vs/workbench/parts/search/browser/searchViewlet.ts @@ -292,7 +292,10 @@ class SearchRenderer extends ActionsRenderer { elements.push(strings.escape(preview.after)); elements.push(''); - $('a.plain').innerHtml(elements.join(strings.empty)).appendTo(domElement); + $('a.plain') + .innerHtml(elements.join(strings.empty)) + .title((preview.before + preview.inside + preview.after).trim().substr(0, 999)) + .appendTo(domElement); } return null; From 4ccab94f2bb6674f2a3d5222962e9345e3325f1f Mon Sep 17 00:00:00 2001 From: Andre Weinand Date: Tue, 10 May 2016 16:41:09 +0200 Subject: [PATCH 129/297] node-debug: support code injection in global context --- extensions/node-debug/node-debug.azure.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/node-debug/node-debug.azure.json b/extensions/node-debug/node-debug.azure.json index ce55ece0d56..b4b4b70c524 100644 --- a/extensions/node-debug/node-debug.azure.json +++ b/extensions/node-debug/node-debug.azure.json @@ -1,6 +1,6 @@ { "account": "monacobuild", "container": "debuggers", - "zip": "39a8b11/node-debug.zip", + "zip": "161b5f4/node-debug.zip", "output": "" } From be5a691a368e664a18f2cc74e182d41f50d8a743 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 10 May 2016 16:42:47 +0200 Subject: [PATCH 130/297] dbk - cd to $ROOT --- scripts/test.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/test.sh b/scripts/test.sh index ee2abda0e4f..7b2ffee0394 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -8,6 +8,7 @@ else ROOT=$(dirname $(dirname $(readlink -f $0))) fi +cd $ROOT pwd # Node modules From 3505aa37bdddf307a47a4e1db2425e9fe328cc21 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Tue, 10 May 2016 17:07:30 +0200 Subject: [PATCH 131/297] fixes #5919: [html] Angular 2 directives break HTML syntax highlighting --- src/vs/languages/html/common/html.ts | 38 ++++++++++++------- .../languages/html/test/common/html.test.ts | 34 ++++++++++++++--- 2 files changed, 54 insertions(+), 18 deletions(-) diff --git a/src/vs/languages/html/common/html.ts b/src/vs/languages/html/common/html.ts index f1b379f8a29..9dff02bf856 100644 --- a/src/vs/languages/html/common/html.ts +++ b/src/vs/languages/html/common/html.ts @@ -85,10 +85,14 @@ export class State extends AbstractState { return false; } - private nextName(stream:Modes.IStream):string { + private nextElementName(stream:Modes.IStream):string { return stream.advanceIfRegExp(/^[_:\w][_:\w-.\d]*/).toLowerCase(); } + private nextAttributeName(stream:Modes.IStream):string { + return stream.advanceIfRegExp(/^[^\s"'>/=\x00-\x0F\x7F\x80-\x9F]*/).toLowerCase(); + } + public tokenize(stream:Modes.IStream) : Modes.ITokenizationResult { switch(this.kind){ @@ -133,7 +137,7 @@ export class State extends AbstractState { break; case States.OpeningEndTag: - var tagName = this.nextName(stream); + var tagName = this.nextElementName(stream); if (tagName.length > 0){ return { type: State.escapeTagName(tagName), @@ -149,7 +153,7 @@ export class State extends AbstractState { } case States.OpeningStartTag: - this.lastTagName = this.nextName(stream); + this.lastTagName = this.nextElementName(stream); if (this.lastTagName.length > 0) { this.lastAttributeName = null; if ('script' === this.lastTagName || 'style' === this.lastTagName) { @@ -165,18 +169,22 @@ export class State extends AbstractState { case States.WithinTag: if (stream.skipWhitespace2() || stream.eos()) { + this.lastAttributeName = ''; // remember that we have seen a whitespace return { type: '' }; } else { - var name:string = this.nextName(stream); - if (name.length > 0) { - this.lastAttributeName = name; - this.kind = States.AttributeName; - return { type: htmlTokenTypes.ATTRIB_NAME }; - - } else if (stream.advanceIfString2('/>')) { - this.kind = States.Content; - return { type: htmlTokenTypes.DELIM_START, dontMergeWithPrev: true }; - } if (stream.advanceIfCharCode2('>'.charCodeAt(0))) { + if (this.lastAttributeName === '') { + var name = this.nextAttributeName(stream); + if (name.length > 0) { + this.lastAttributeName = name; + this.kind = States.AttributeName; + return { type: htmlTokenTypes.ATTRIB_NAME }; + } + } + if (stream.advanceIfString2('/>')) { + this.kind = States.Content; + return { type: htmlTokenTypes.DELIM_START, dontMergeWithPrev: true }; + } + if (stream.advanceIfCharCode2('>'.charCodeAt(0))) { if (tagsEmbeddingContent.indexOf(this.lastTagName) !== -1) { this.kind = States.WithinEmbeddedContent; return { type: htmlTokenTypes.DELIM_START, dontMergeWithPrev: true }; @@ -200,6 +208,7 @@ export class State extends AbstractState { return { type: htmlTokenTypes.DELIM_ASSIGN }; } else { this.kind = States.WithinTag; + this.lastAttributeName = ''; return this.tokenize(stream); // no advance yet - jump to WithinTag } @@ -231,6 +240,7 @@ export class State extends AbstractState { this.kind = States.WithinTag; this.attributeValue = ''; this.attributeValueQuote = ''; + this.lastAttributeName = null; } else { var part = stream.next(); this.attributeValue += part; @@ -241,6 +251,7 @@ export class State extends AbstractState { let attributeValue = stream.advanceIfRegExp(/^[^\s"'`=<>]+/); if (attributeValue.length > 0) { this.kind = States.WithinTag; + this.lastAttributeName = null; return { type: htmlTokenTypes.ATTRIB_VALUE }; } var ch = stream.peek(); @@ -251,6 +262,7 @@ export class State extends AbstractState { return { type: htmlTokenTypes.ATTRIB_VALUE }; } else { this.kind = States.WithinTag; + this.lastAttributeName = null; return this.tokenize(stream); // no advance yet - jump to WithinTag } } diff --git a/src/vs/languages/html/test/common/html.test.ts b/src/vs/languages/html/test/common/html.test.ts index 1fc0e908554..815d37c56d2 100644 --- a/src/vs/languages/html/test/common/html.test.ts +++ b/src/vs/languages/html/test/common/html.test.ts @@ -466,7 +466,7 @@ suite('Colorizing - HTML', () => { ]); }); - test('Tag with empty atrributes', () => { + test('Tag with empty attributes', () => { modesUtil.assertTokenization(tokenizationSupport, [{ line: '', tokens: [ @@ -580,7 +580,7 @@ suite('Colorizing - HTML', () => { ]); }); - test('Tag with Invalid Attribute Name', () => { + test('Tag with Interesting Attribute Name', () => { modesUtil.assertTokenization(tokenizationSupport, [{ line: '', tokens: [ @@ -588,14 +588,38 @@ suite('Colorizing - HTML', () => { { startIndex:1, type: getTag('abc') }, { startIndex:4, type: '' }, { startIndex:5, type: ATTRIB_NAME }, - { startIndex:8, type: '' }, - { startIndex:13, type: ATTRIB_NAME }, - { startIndex:16, type: '' }, + { startIndex:11, type: DELIM_ASSIGN }, + { startIndex:12, type: ATTRIB_VALUE }, { startIndex:17, type: DELIM_START } ]} ]); }); + test('Tag with Angular Attribute Name', () => { + modesUtil.assertTokenization(tokenizationSupport, [{ + line: '', + tokens: [ + { startIndex:0, type: DELIM_START }, + { startIndex:1, type: getTag('abc') }, + { startIndex:4, type: '' }, + { startIndex:5, type: ATTRIB_NAME }, + { startIndex:13, type: '' }, + { startIndex:14, type: ATTRIB_NAME }, + { startIndex:21, type: DELIM_ASSIGN }, + { startIndex:22, type: ATTRIB_VALUE }, + { startIndex:27, type: '' }, + { startIndex:28, type: ATTRIB_NAME }, + { startIndex:35, type: DELIM_ASSIGN }, + { startIndex:36, type: ATTRIB_VALUE }, + { startIndex:50, type: '' }, + { startIndex:51, type: ATTRIB_NAME }, + { startIndex:56, type: DELIM_ASSIGN }, + { startIndex:57, type: ATTRIB_VALUE }, + { startIndex:72, type: DELIM_START } + ]} + ]); + }); + test('Tag with Invalid Attribute Value', () => { modesUtil.assertTokenization(tokenizationSupport, [{ line: ' this.extensionService.onReady() + .then(() => this.configurationManager.setConfiguration((this.configurationManager.configurationName)) + .then(() => { + this.configurationManager.resloveConfiguration(configuration); + configuration = configuration || this.configurationManager.configuration; + if (!configuration) { + return this.configurationManager.openConfigFile(false).then(openend => { + if (openend) { + this.messageService.show(severity.Info, nls.localize('NewLaunchConfig', "Please set up the launch configuration file for your application.")); + } + }); + } - configuration.noDebug = noDebug; - if (!this.configurationManager.adapter) { - return configuration.type ? TPromise.wrapError(new Error(nls.localize('debugTypeNotSupported', "Configured debug type '{0}' is not supported.", configuration.type))) - : TPromise.wrapError(errors.create(nls.localize('debugTypeMissing', "Missing property 'type' for the selected configuration in launch.json."), - { actions: [CloseAction, this.instantiationService.createInstance(debugactions.ConfigureAction, debugactions.ConfigureAction.ID, debugactions.ConfigureAction.LABEL)] })); - } + configuration.noDebug = noDebug; + if (!this.configurationManager.adapter) { + return configuration.type ? TPromise.wrapError(new Error(nls.localize('debugTypeNotSupported', "Configured debug type '{0}' is not supported.", configuration.type))) + : TPromise.wrapError(errors.create(nls.localize('debugTypeMissing', "Missing property 'type' for the selected configuration in launch.json."), + { actions: [CloseAction, this.instantiationService.createInstance(debugactions.ConfigureAction, debugactions.ConfigureAction.ID, debugactions.ConfigureAction.LABEL)] })); + } - return this.runPreLaunchTask(configuration.preLaunchTask).then((taskSummary: ITaskSummary) => { - const errorCount = configuration.preLaunchTask ? this.markerService.getStatistics().errors : 0; - const successExitCode = taskSummary && taskSummary.exitCode === 0; - const failureExitCode = taskSummary && taskSummary.exitCode !== undefined && taskSummary.exitCode !== 0; - if (successExitCode || (errorCount === 0 && !failureExitCode)) { - return this.doCreateSession(configuration, changeViewState); - } + return this.runPreLaunchTask(configuration.preLaunchTask).then((taskSummary: ITaskSummary) => { + const errorCount = configuration.preLaunchTask ? this.markerService.getStatistics().errors : 0; + const successExitCode = taskSummary && taskSummary.exitCode === 0; + const failureExitCode = taskSummary && taskSummary.exitCode !== undefined && taskSummary.exitCode !== 0; + if (successExitCode || (errorCount === 0 && !failureExitCode)) { + return this.doCreateSession(configuration, changeViewState); + } - this.messageService.show(severity.Error, { - message: errorCount > 1 ? nls.localize('preLaunchTaskErrors', "Build errors have been detected during preLaunchTask '{0}'.", configuration.preLaunchTask) : - errorCount === 1 ? nls.localize('preLaunchTaskError', "Build error has been detected during preLaunchTask '{0}'.", configuration.preLaunchTask) : - nls.localize('preLaunchTaskExitCode', "The preLaunchTask '{0}' terminated with exit code {1}.", configuration.preLaunchTask, taskSummary.exitCode), - actions: [CloseAction, new Action('debug.continue', nls.localize('debugAnyway', "Debug Anyway"), null, true, () => { - this.messageService.hideAll(); - return this.doCreateSession(configuration, changeViewState); - })] - }); - }, (err: TaskError) => { - if (err.code !== TaskErrors.NotConfigured) { - throw err; - } + this.messageService.show(severity.Error, { + message: errorCount > 1 ? nls.localize('preLaunchTaskErrors', "Build errors have been detected during preLaunchTask '{0}'.", configuration.preLaunchTask) : + errorCount === 1 ? nls.localize('preLaunchTaskError', "Build error has been detected during preLaunchTask '{0}'.", configuration.preLaunchTask) : + nls.localize('preLaunchTaskExitCode', "The preLaunchTask '{0}' terminated with exit code {1}.", configuration.preLaunchTask, taskSummary.exitCode), + actions: [CloseAction, new Action('debug.continue', nls.localize('debugAnyway', "Debug Anyway"), null, true, () => { + this.messageService.hideAll(); + return this.doCreateSession(configuration, changeViewState); + })] + }); + }, (err: TaskError) => { + if (err.code !== TaskErrors.NotConfigured) { + throw err; + } - this.messageService.show(err.severity, { - message: err.message, - actions: [CloseAction, this.taskService.configureAction()] - }); - }); - })))); + this.messageService.show(err.severity, { + message: err.message, + actions: [CloseAction, this.taskService.configureAction()] + }); + }); + })))); } private doCreateSession(configuration: debug.IConfig, changeViewState: boolean): TPromise { @@ -679,10 +680,10 @@ export class DebugService implements debug.IDebugService { return this.session ? this.session.disconnect(true).then(() => new TPromise((c, e) => { setTimeout(() => { - this.createSession(false, false).then(() => c(null), err => e(err)); + this.createSession(false, null, false).then(() => c(null), err => e(err)); }, 300); }) - ) : this.createSession(false, false); + ) : this.createSession(false, null, false); } public getActiveSession(): debug.IRawDebugSession { diff --git a/src/vs/workbench/parts/debug/node/debugConfigurationManager.ts b/src/vs/workbench/parts/debug/node/debugConfigurationManager.ts index 329ed1ce631..390be54194e 100644 --- a/src/vs/workbench/parts/debug/node/debugConfigurationManager.ts +++ b/src/vs/workbench/parts/debug/node/debugConfigurationManager.ts @@ -241,16 +241,20 @@ export class ConfigurationManager implements debug.IConfigurationManager { // massage configuration attributes - append workspace path to relatvie paths, substitute variables in paths. this.configuration = filtered.length === 1 ? objects.deepClone(filtered[0]) : null; if (this.configuration) { - if (this.systemVariables) { - Object.keys(this.configuration).forEach(key => { - this.configuration[key] = this.systemVariables.resolveAny(this.configuration[key]); - }); - } + this.resloveConfiguration(this.configuration); this.configuration.debugServer = config.debugServer; } }).then(() => this._onDidConfigurationChange.fire(this.configurationName)); } + public resloveConfiguration(configuration: debug.IConfig) { + if (this.systemVariables && configuration) { + Object.keys(configuration).forEach(key => { + configuration[key] = this.systemVariables.resolveAny(configuration[key]); + }); + } + } + public openConfigFile(sideBySide: boolean): TPromise { const resource = uri.file(paths.join(this.contextService.getWorkspace().resource.fsPath, '/.vscode/launch.json')); From 409a875c45ad08cf496a5544fc19fce6e0b4410c Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 10 May 2016 18:47:28 +0200 Subject: [PATCH 135/297] perf - shave off ~4ms from startup by using a better isObject-implementation --- src/vs/base/common/types.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/vs/base/common/types.ts b/src/vs/base/common/types.ts index 0da219e3d00..7f41a76c996 100644 --- a/src/vs/base/common/types.ts +++ b/src/vs/base/common/types.ts @@ -40,16 +40,16 @@ export function isStringArray(value: any): value is string[] { } /** - * @returns whether the provided parameter is a JavaScript Object or not. + * + * @returns whether the provided parameter is of type `object` but **not** + * `null`, an `array`, a `regexp`, nor a `date`. */ export function isObject(obj: any): obj is any { - - // Needed for IE8 - if (typeof obj === 'undefined' || obj === null) { - return false; - } - - return Object.prototype.toString.call(obj) === '[object Object]'; + return typeof obj === 'object' + && obj !== null + && !Array.isArray(obj) + && !(obj instanceof RegExp) + && !(obj instanceof Date); } /** From 5caae080f59dbfda40dcfb9c95dd0d731a0353b5 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 10 May 2016 19:22:12 +0200 Subject: [PATCH 136/297] gettingStarted => welcome --- .../common/abstractGettingStarted.ts | 0 .../electron-browser/electronGettingStarted.contribution.ts | 2 +- .../electron-browser/electronGettingStarted.ts | 2 +- .../test/common/gettingStarted.test.ts | 2 +- src/vs/workbench/workbench.main.js | 2 +- 5 files changed, 4 insertions(+), 4 deletions(-) rename src/vs/workbench/parts/{gettingStarted => welcome}/common/abstractGettingStarted.ts (100%) rename src/vs/workbench/parts/{gettingStarted => welcome}/electron-browser/electronGettingStarted.contribution.ts (85%) rename src/vs/workbench/parts/{gettingStarted => welcome}/electron-browser/electronGettingStarted.ts (91%) rename src/vs/workbench/parts/{gettingStarted => welcome}/test/common/gettingStarted.test.ts (96%) diff --git a/src/vs/workbench/parts/gettingStarted/common/abstractGettingStarted.ts b/src/vs/workbench/parts/welcome/common/abstractGettingStarted.ts similarity index 100% rename from src/vs/workbench/parts/gettingStarted/common/abstractGettingStarted.ts rename to src/vs/workbench/parts/welcome/common/abstractGettingStarted.ts diff --git a/src/vs/workbench/parts/gettingStarted/electron-browser/electronGettingStarted.contribution.ts b/src/vs/workbench/parts/welcome/electron-browser/electronGettingStarted.contribution.ts similarity index 85% rename from src/vs/workbench/parts/gettingStarted/electron-browser/electronGettingStarted.contribution.ts rename to src/vs/workbench/parts/welcome/electron-browser/electronGettingStarted.contribution.ts index 1392847beb2..62234222c0e 100644 --- a/src/vs/workbench/parts/gettingStarted/electron-browser/electronGettingStarted.contribution.ts +++ b/src/vs/workbench/parts/welcome/electron-browser/electronGettingStarted.contribution.ts @@ -5,7 +5,7 @@ 'use strict'; import {Registry} from 'vs/platform/platform'; -import {ElectronGettingStarted} from 'vs/workbench/parts/gettingStarted/electron-browser/electronGettingStarted'; +import {ElectronGettingStarted} from 'vs/workbench/parts/welcome/electron-browser/electronGettingStarted'; import {IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions} from 'vs/workbench/common/contributions'; (Registry.as(WorkbenchExtensions.Workbench)).registerWorkbenchContribution( diff --git a/src/vs/workbench/parts/gettingStarted/electron-browser/electronGettingStarted.ts b/src/vs/workbench/parts/welcome/electron-browser/electronGettingStarted.ts similarity index 91% rename from src/vs/workbench/parts/gettingStarted/electron-browser/electronGettingStarted.ts rename to src/vs/workbench/parts/welcome/electron-browser/electronGettingStarted.ts index 90d847fa3e4..265c486e306 100644 --- a/src/vs/workbench/parts/gettingStarted/electron-browser/electronGettingStarted.ts +++ b/src/vs/workbench/parts/welcome/electron-browser/electronGettingStarted.ts @@ -5,7 +5,7 @@ 'use strict'; import {IWorkbenchContribution} from 'vs/workbench/common/contributions'; -import {AbstractGettingStarted} from 'vs/workbench/parts/gettingStarted/common/abstractGettingStarted'; +import {AbstractGettingStarted} from 'vs/workbench/parts/welcome/common/abstractGettingStarted'; import * as platform from 'vs/base/common/platform'; import { shell } from 'electron'; diff --git a/src/vs/workbench/parts/gettingStarted/test/common/gettingStarted.test.ts b/src/vs/workbench/parts/welcome/test/common/gettingStarted.test.ts similarity index 96% rename from src/vs/workbench/parts/gettingStarted/test/common/gettingStarted.test.ts rename to src/vs/workbench/parts/welcome/test/common/gettingStarted.test.ts index d384e5c69a8..894c0c7aecd 100644 --- a/src/vs/workbench/parts/gettingStarted/test/common/gettingStarted.test.ts +++ b/src/vs/workbench/parts/welcome/test/common/gettingStarted.test.ts @@ -6,7 +6,7 @@ 'use strict'; import * as assert from 'assert'; -import {AbstractGettingStarted} from 'vs/workbench/parts/gettingStarted/common/abstractGettingStarted'; +import {AbstractGettingStarted} from 'vs/workbench/parts/welcome/common/abstractGettingStarted'; import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation'; import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace'; import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry'; diff --git a/src/vs/workbench/workbench.main.js b/src/vs/workbench/workbench.main.js index 50dd40c046d..9b970c02b4e 100644 --- a/src/vs/workbench/workbench.main.js +++ b/src/vs/workbench/workbench.main.js @@ -78,7 +78,7 @@ define([ 'vs/workbench/parts/feedback/electron-browser/feedback.contribution', - 'vs/workbench/parts/gettingStarted/electron-browser/electronGettingStarted.contribution', + 'vs/workbench/parts/welcome/electron-browser/electronGettingStarted.contribution', 'vs/workbench/parts/update/electron-browser/update.contribution', From e0d75419feb04cf4b965676b3f70720e84946c76 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Tue, 10 May 2016 18:30:24 +0200 Subject: [PATCH 137/297] fixes #4101: [html] Why editor.action.smartSelect is not working in html file? --- src/vs/editor/common/modes.ts | 16 ----------- .../contrib/smartSelect/common/smartSelect.ts | 7 ++--- .../common/tokenSelectionSupport.ts | 11 ++++++-- src/vs/languages/css/common/css.ts | 7 ----- src/vs/languages/css/common/cssWorker.ts | 28 ------------------- src/vs/languages/html/common/html.ts | 7 ----- src/vs/languages/html/common/htmlWorker.ts | 8 ------ src/vs/languages/less/common/less.ts | 7 ----- src/vs/languages/sass/common/sass.ts | 7 ----- 9 files changed, 11 insertions(+), 87 deletions(-) diff --git a/src/vs/editor/common/modes.ts b/src/vs/editor/common/modes.ts index bb81831fd64..96e2d02ba00 100644 --- a/src/vs/editor/common/modes.ts +++ b/src/vs/editor/common/modes.ts @@ -226,11 +226,6 @@ export interface IMode { */ outlineSupport?:IOutlineSupport; - /** - * Optional adapter to support logical selection. - */ - logicalSelectionSupport?:ILogicalSelectionSupport; - /** * Optional adapter to support formatting. */ @@ -503,17 +498,6 @@ export interface IOutlineSupport { outlineGroupLabel?: { [name: string]: string; }; } -/** - * Interface used to compute a hierachry of logical ranges. - */ -export interface ILogicalSelectionEntry { - type:string; - range:editorCommon.IRange; -} -export interface ILogicalSelectionSupport { - getRangesToPosition(resource:URI, position:editorCommon.IPosition):TPromise; -} - /** * Interface used to format a model */ diff --git a/src/vs/editor/contrib/smartSelect/common/smartSelect.ts b/src/vs/editor/contrib/smartSelect/common/smartSelect.ts index 0c4d46fb553..17013fdad00 100644 --- a/src/vs/editor/contrib/smartSelect/common/smartSelect.ts +++ b/src/vs/editor/contrib/smartSelect/common/smartSelect.ts @@ -14,8 +14,7 @@ import {EditorAction} from 'vs/editor/common/editorAction'; import {Behaviour} from 'vs/editor/common/editorActionEnablement'; import {EventType, ICommonCodeEditor, ICursorPositionChangedEvent, IEditorActionDescriptorData, IEditorRange} from 'vs/editor/common/editorCommon'; import {CommonEditorRegistry, ContextKey, EditorActionDescriptor} from 'vs/editor/common/editorCommonExtensions'; -import {ILogicalSelectionEntry} from 'vs/editor/common/modes'; -import {TokenSelectionSupport} from './tokenSelectionSupport'; +import {TokenSelectionSupport, ILogicalSelectionEntry} from './tokenSelectionSupport'; // --- selection state machine @@ -55,7 +54,6 @@ class SmartSelect extends EditorAction { var selection = this.editor.getSelection(); var model = this.editor.getModel(); - var selectionSupport = model.getMode().logicalSelectionSupport || this._tokenSelectionSupport; // forget about current state if (state) { @@ -66,8 +64,7 @@ class SmartSelect extends EditorAction { var promise:TPromise = TPromise.as(null); if (!state) { - - promise = selectionSupport.getRangesToPosition(model.getAssociatedResource(), selection.getStartPosition()).then((elements: ILogicalSelectionEntry[]) => { + promise = this._tokenSelectionSupport.getRangesToPosition(model.getAssociatedResource(), selection.getStartPosition()).then((elements: ILogicalSelectionEntry[]) => { if (arrays.isFalsyOrEmpty(elements)) { return; diff --git a/src/vs/editor/contrib/smartSelect/common/tokenSelectionSupport.ts b/src/vs/editor/contrib/smartSelect/common/tokenSelectionSupport.ts index 2935372261a..eb8096d7c7b 100644 --- a/src/vs/editor/contrib/smartSelect/common/tokenSelectionSupport.ts +++ b/src/vs/editor/contrib/smartSelect/common/tokenSelectionSupport.ts @@ -8,11 +8,18 @@ import URI from 'vs/base/common/uri'; import {TPromise} from 'vs/base/common/winjs.base'; import {Range} from 'vs/editor/common/core/range'; import {IModel, IPosition, IRange} from 'vs/editor/common/editorCommon'; -import {ILogicalSelectionEntry, ILogicalSelectionSupport} from 'vs/editor/common/modes'; import {IModelService} from 'vs/editor/common/services/modelService'; import {Node, build, find} from './tokenTree'; -export class TokenSelectionSupport implements ILogicalSelectionSupport { +/** + * Interface used to compute a hierachry of logical ranges. + */ +export interface ILogicalSelectionEntry { + type:string; + range:IRange; +} + +export class TokenSelectionSupport { private _modelService: IModelService; diff --git a/src/vs/languages/css/common/css.ts b/src/vs/languages/css/common/css.ts index 203566d1013..3cdfeeaaccc 100644 --- a/src/vs/languages/css/common/css.ts +++ b/src/vs/languages/css/common/css.ts @@ -283,7 +283,6 @@ export class CSSMode extends AbstractMode { public inplaceReplaceSupport:Modes.IInplaceReplaceSupport; public configSupport:Modes.IConfigurationSupport; public referenceSupport: Modes.IReferenceSupport; - public logicalSelectionSupport: Modes.ILogicalSelectionSupport; public extraInfoSupport:Modes.IExtraInfoSupport; public occurrencesSupport:Modes.IOccurrencesSupport; public outlineSupport: Modes.IOutlineSupport; @@ -339,7 +338,6 @@ export class CSSMode extends AbstractMode { // this.referenceSupport = new ReferenceSupport(this.getId(), { // tokens: [cssTokenTypes.TOKEN_PROPERTY + '.css', cssTokenTypes.TOKEN_VALUE + '.css', cssTokenTypes.TOKEN_SELECTOR_TAG + '.css'], // findReferences: (resource, position, /*unused*/includeDeclaration) => this.findReferences(resource, position)}); - this.logicalSelectionSupport = this; this.outlineSupport = this; // this.declarationSupport = new DeclarationSupport(this.getId(), { // tokens: [cssTokenTypes.TOKEN_VALUE + '.css'], @@ -413,11 +411,6 @@ export class CSSMode extends AbstractMode { return this._worker((w) => w.findReferences(resource, position)); } - static $getRangesToPosition = OneWorkerAttr(CSSMode, CSSMode.prototype.getRangesToPosition); - public getRangesToPosition(resource:URI, position:EditorCommon.IPosition):WinJS.TPromise { - return this._worker((w) => w.getRangesToPosition(resource, position)); - } - static $getOutline = OneWorkerAttr(CSSMode, CSSMode.prototype.getOutline); public getOutline(resource:URI):WinJS.TPromise { return this._worker((w) => w.getOutline(resource)); diff --git a/src/vs/languages/css/common/cssWorker.ts b/src/vs/languages/css/common/cssWorker.ts index 1541e2fd2b6..dae04dd0b34 100644 --- a/src/vs/languages/css/common/cssWorker.ts +++ b/src/vs/languages/css/common/cssWorker.ts @@ -210,34 +210,6 @@ export class CSSWorker { } - public getRangesToPosition(resource:URI, position:EditorCommon.IPosition):winjs.TPromise { - - return this.languageService.join().then(() => { - - let model = this.resourceService.get(resource), - offset = model.getOffsetFromPosition(position), - styleSheet = this.languageService.getStylesheet(resource), - path = nodes.getNodePath(styleSheet, offset), - result: Modes.ILogicalSelectionEntry[] = []; - - for (let i = 0; i < path.length; i++) { - let node = path[i]; - if(node.offset === -1 || node.length === -1) { - continue; - } - if(node.parent && node.parent.offset === node.offset && node.parent.length === node.length) { - continue; - } - result.push({ - type: 'node', - range: this._range(node, model) - }); - } - - return result; - }); - } - public getOutline(resource:URI):winjs.TPromise { return this.languageService.join().then(() => { diff --git a/src/vs/languages/html/common/html.ts b/src/vs/languages/html/common/html.ts index 9dff02bf856..adbc95bf164 100644 --- a/src/vs/languages/html/common/html.ts +++ b/src/vs/languages/html/common/html.ts @@ -294,7 +294,6 @@ export class HTMLMode extends AbstractMode impl public extraInfoSupport:Modes.IExtraInfoSupport; public occurrencesSupport:Modes.IOccurrencesSupport; public referenceSupport: Modes.IReferenceSupport; - public logicalSelectionSupport: Modes.ILogicalSelectionSupport; public formattingSupport: Modes.IFormattingSupport; public parameterHintsSupport: Modes.IParameterHintsSupport; public suggestSupport: Modes.ISuggestSupport; @@ -325,7 +324,6 @@ export class HTMLMode extends AbstractMode impl this.referenceSupport = new ReferenceSupport(this.getId(), { tokens: ['invalid'], findReferences: (resource, position, includeDeclaration) => this.findReferences(resource, position, includeDeclaration)}); - this.logicalSelectionSupport = this; this.parameterHintsSupport = new ParameterHintsSupport(this.getId(), { triggerCharacters: ['(', ','], @@ -495,11 +493,6 @@ export class HTMLMode extends AbstractMode impl return this._worker((w) => w.findReferences(resource, position, includeDeclaration)); } - static $getRangesToPosition = OneWorkerAttr(HTMLMode, HTMLMode.prototype.getRangesToPosition); - public getRangesToPosition(resource:URI, position:EditorCommon.IPosition):winjs.TPromise { - return this._worker((w) => w.getRangesToPosition(resource, position)); - } - static $findDeclaration = OneWorkerAttr(HTMLMode, HTMLMode.prototype.findDeclaration); public findDeclaration(resource:URI, position:EditorCommon.IPosition):winjs.TPromise { return this._worker((w) => w.findDeclaration(resource, position)); diff --git a/src/vs/languages/html/common/htmlWorker.ts b/src/vs/languages/html/common/htmlWorker.ts index ee8e784f6f7..f975961c9c8 100644 --- a/src/vs/languages/html/common/htmlWorker.ts +++ b/src/vs/languages/html/common/htmlWorker.ts @@ -166,14 +166,6 @@ export class HTMLWorker { }); } - public getRangesToPosition(resource:URI, position:EditorCommon.IPosition):winjs.TPromise { - return this._delegateToModeAtPosition(resource, position, (isEmbeddedMode, model) => { - if (isEmbeddedMode && model.getMode().logicalSelectionSupport) { - return model.getMode().logicalSelectionSupport.getRangesToPosition(model.getAssociatedResource(), position); - } - }); - } - public findDeclaration(resource:URI, position:EditorCommon.IPosition):winjs.TPromise { return this._delegateToModeAtPosition(resource, position, (isEmbeddedMode, model) => { if (isEmbeddedMode && model.getMode().declarationSupport) { diff --git a/src/vs/languages/less/common/less.ts b/src/vs/languages/less/common/less.ts index 2f0e3815bcd..3888b763c89 100644 --- a/src/vs/languages/less/common/less.ts +++ b/src/vs/languages/less/common/less.ts @@ -181,7 +181,6 @@ export class LESSMode extends Monarch.MonarchMode implements Modes.IExtraInfoSup public inplaceReplaceSupport:Modes.IInplaceReplaceSupport; public configSupport:Modes.IConfigurationSupport; public referenceSupport: Modes.IReferenceSupport; - public logicalSelectionSupport: Modes.ILogicalSelectionSupport; public extraInfoSupport: Modes.IExtraInfoSupport; public declarationSupport: Modes.IDeclarationSupport; public outlineSupport: Modes.IOutlineSupport; @@ -211,7 +210,6 @@ export class LESSMode extends Monarch.MonarchMode implements Modes.IExtraInfoSup this.referenceSupport = new ReferenceSupport(this.getId(), { tokens: [lessTokenTypes.TOKEN_PROPERTY + '.less', lessTokenTypes.TOKEN_VALUE + '.less', 'variable.less', lessTokenTypes.TOKEN_SELECTOR + '.class.less', lessTokenTypes.TOKEN_SELECTOR + '.id.less', 'selector.less'], findReferences: (resource, position, /*unused*/includeDeclaration) => this.findReferences(resource, position)}); - this.logicalSelectionSupport = this; this.declarationSupport = new DeclarationSupport(this.getId(), { tokens: ['variable.less', lessTokenTypes.TOKEN_SELECTOR + '.class.less', lessTokenTypes.TOKEN_SELECTOR + '.id.less', 'selector.less'], findDeclaration: (resource, position) => this.findDeclaration(resource, position)}); @@ -267,11 +265,6 @@ export class LESSMode extends Monarch.MonarchMode implements Modes.IExtraInfoSup return this._worker((w) => w.suggest(resource, position)); } - static $getRangesToPosition = OneWorkerAttr(LESSMode, LESSMode.prototype.getRangesToPosition); - public getRangesToPosition(resource:URI, position:EditorCommon.IPosition):winjs.TPromise { - return this._worker((w) => w.getRangesToPosition(resource, position)); - } - static $computeInfo = OneWorkerAttr(LESSMode, LESSMode.prototype.computeInfo); public computeInfo(resource:URI, position:EditorCommon.IPosition): winjs.TPromise { return this._worker((w) => w.computeInfo(resource, position)); diff --git a/src/vs/languages/sass/common/sass.ts b/src/vs/languages/sass/common/sass.ts index b566c8717db..4d265627143 100644 --- a/src/vs/languages/sass/common/sass.ts +++ b/src/vs/languages/sass/common/sass.ts @@ -283,7 +283,6 @@ export class SASSMode extends Monarch.MonarchMode implements Modes.IExtraInfoSup public inplaceReplaceSupport:Modes.IInplaceReplaceSupport; public configSupport:Modes.IConfigurationSupport; public referenceSupport: Modes.IReferenceSupport; - public logicalSelectionSupport: Modes.ILogicalSelectionSupport; public extraInfoSupport: Modes.IExtraInfoSupport; public outlineSupport: Modes.IOutlineSupport; public declarationSupport: Modes.IDeclarationSupport; @@ -313,7 +312,6 @@ export class SASSMode extends Monarch.MonarchMode implements Modes.IExtraInfoSup this.referenceSupport = new ReferenceSupport(this.getId(), { tokens: [sassTokenTypes.TOKEN_PROPERTY + '.sass', sassTokenTypes.TOKEN_VALUE + '.sass', 'variable.decl.sass', 'variable.ref.sass', 'support.function.name.sass', sassTokenTypes.TOKEN_PROPERTY + '.sass', sassTokenTypes.TOKEN_SELECTOR + '.sass'], findReferences: (resource, position, /*unused*/includeDeclaration) => this.findReferences(resource, position)}); - this.logicalSelectionSupport = this; this.declarationSupport = new DeclarationSupport(this.getId(), { tokens: ['variable.decl.sass', 'variable.ref.sass', 'support.function.name.sass', sassTokenTypes.TOKEN_PROPERTY + '.sass', sassTokenTypes.TOKEN_SELECTOR + '.sass'], findDeclaration: (resource, position) => this.findDeclaration(resource, position)}); @@ -369,11 +367,6 @@ export class SASSMode extends Monarch.MonarchMode implements Modes.IExtraInfoSup return this._worker((w) => w.suggest(resource, position)); } - static $getRangesToPosition = OneWorkerAttr(SASSMode, SASSMode.prototype.getRangesToPosition); - public getRangesToPosition(resource:URI, position:EditorCommon.IPosition):winjs.TPromise { - return this._worker((w) => w.getRangesToPosition(resource, position)); - } - static $computeInfo = OneWorkerAttr(SASSMode, SASSMode.prototype.computeInfo); public computeInfo(resource:URI, position:EditorCommon.IPosition): winjs.TPromise { return this._worker((w) => w.computeInfo(resource, position)); From 0a8ae305fa7b1db1d27c69ac281dc7238bda9faf Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Tue, 10 May 2016 21:55:55 +0200 Subject: [PATCH 138/297] fixes #6243: [html] Cannot get close tag suggestions for HTML after updating to 1.1.0 --- src/vs/languages/html/common/htmlWorker.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/vs/languages/html/common/htmlWorker.ts b/src/vs/languages/html/common/htmlWorker.ts index f975961c9c8..2685061bc75 100644 --- a/src/vs/languages/html/common/htmlWorker.ts +++ b/src/vs/languages/html/common/htmlWorker.ts @@ -225,7 +225,8 @@ export class HTMLWorker { private collectTagSuggestions(scanner: IHTMLScanner, position: EditorCommon.IPosition, suggestions: Modes.ISuggestResult): void { let model = scanner.getModel(); - let contentAfter = model.getLineContent(position.lineNumber).substr(position.column - 1); + let currentLine = model.getLineContent(position.lineNumber); + let contentAfter = currentLine.substr(position.column - 1); let closeTag = isWhiteSpace(contentAfter) || strings.startsWith(contentAfter, '<') ? '>' : ''; let collectClosingTagSuggestion = (overwriteBefore: number) => { @@ -248,6 +249,7 @@ export class HTMLWorker { if (isWhiteSpace(startIndent) && isWhiteSpace(endIndent)) { suggestion.overwriteBefore = position.column - 1; // replace from start of line suggestion.codeSnippet = startIndent + ' Date: Wed, 11 May 2016 09:21:36 +0200 Subject: [PATCH 139/297] windows has more common properties, fix test failure --- src/vs/platform/telemetry/test/node/commonProperties.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/platform/telemetry/test/node/commonProperties.test.ts b/src/vs/platform/telemetry/test/node/commonProperties.test.ts index 7fccae2ff8a..10b9e1a101a 100644 --- a/src/vs/platform/telemetry/test/node/commonProperties.test.ts +++ b/src/vs/platform/telemetry/test/node/commonProperties.test.ts @@ -15,7 +15,7 @@ suite('Telemetry - common properties', function () { return resolveCommonProperties(new TestStorageService(), new TestContextService()).then(props => { - assert.equal(Object.keys(props).length, 15); + assert.equal(Object.keys(props).length, process.platform === 'win32' ? 17 : 15); assert.ok('commitHash' in props); assert.ok('sessionID' in props); From 8234a41a4b4f120a13d72e40f990003c0d36c55c Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 11 May 2016 09:57:10 +0200 Subject: [PATCH 140/297] use typeof-check for isFunction, store expected typeof outcomes --- src/vs/base/common/types.ts | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/src/vs/base/common/types.ts b/src/vs/base/common/types.ts index 7f41a76c996..1d24c6b29fc 100644 --- a/src/vs/base/common/types.ts +++ b/src/vs/base/common/types.ts @@ -6,6 +6,14 @@ import {TPromise} from 'vs/base/common/winjs.base'; +const _typeof = { + number: 'number', + string: 'string', + undefined: 'undefined', + object: 'object', + function: 'function' +}; + /** * @returns whether the provided parameter is a JavaScript Array or not. */ @@ -14,7 +22,7 @@ export function isArray(array: any): array is any[] { return Array.isArray(array); } - if (array && typeof (array.length) === 'number' && array.constructor === Array) { + if (array && typeof (array.length) === _typeof.number && array.constructor === Array) { return true; } @@ -25,7 +33,7 @@ export function isArray(array: any): array is any[] { * @returns whether the provided parameter is a JavaScript String or not. */ export function isString(str: any): str is string { - if (typeof (str) === 'string' || str instanceof String) { + if (typeof (str) === _typeof.string|| str instanceof String) { return true; } @@ -45,7 +53,7 @@ export function isStringArray(value: any): value is string[] { * `null`, an `array`, a `regexp`, nor a `date`. */ export function isObject(obj: any): obj is any { - return typeof obj === 'object' + return typeof obj === _typeof.object && obj !== null && !Array.isArray(obj) && !(obj instanceof RegExp) @@ -53,10 +61,11 @@ export function isObject(obj: any): obj is any { } /** + * In **contrast** to just checking `typeof` this will return `false` for `NaN`. * @returns whether the provided parameter is a JavaScript Number or not. */ export function isNumber(obj: any): obj is number { - if ((typeof (obj) === 'number' || obj instanceof Number) && !isNaN(obj)) { + if ((typeof (obj) === _typeof.number || obj instanceof Number) && !isNaN(obj)) { return true; } @@ -74,7 +83,7 @@ export function isBoolean(obj: any): obj is boolean { * @returns whether the provided parameter is undefined. */ export function isUndefined(obj: any): boolean { - return typeof (obj) === 'undefined'; + return typeof (obj) === _typeof.undefined; } /** @@ -108,14 +117,14 @@ export function isEmptyObject(obj: any): obj is any { * @returns whether the provided parameter is a JavaScript Function or not. */ export function isFunction(obj: any): obj is Function { - return Object.prototype.toString.call(obj) === '[object Function]'; + return typeof obj === _typeof.function; } /** * @returns whether the provided parameters is are JavaScript Function or not. */ export function areFunctions(...objects: any[]): boolean { - return objects && objects.length > 0 && objects.every((object) => isFunction(object)); + return objects && objects.length > 0 && objects.every(isFunction); } export type TypeConstraint = string | Function; @@ -129,11 +138,11 @@ export function validateConstraints(args: any[], constraints: TypeConstraint[]): export function validateConstraint(arg: any, constraint: TypeConstraint): void { - if (typeof constraint === 'string') { + if (isString(constraint)) { if (typeof arg !== constraint) { throw new Error(`argument does not match constraint: typeof ${constraint}`); } - } else if (typeof constraint === 'function') { + } else if (isFunction(constraint)) { if (arg instanceof constraint) { return; } From 1fc99552bc2141a947ca46ab3e95d3e38592c38a Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 11 May 2016 10:19:58 +0200 Subject: [PATCH 141/297] remove unused code --- src/vs/base/common/objects.ts | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/vs/base/common/objects.ts b/src/vs/base/common/objects.ts index 5d99959db66..c0c16274968 100644 --- a/src/vs/base/common/objects.ts +++ b/src/vs/base/common/objects.ts @@ -151,14 +151,6 @@ export function toObject(arr: T[], keyMap: (T) => string, valueMap: (T) => return arr.reduce((o, d) => assign(o, { [keyMap(d)]: valueMap(d) }), Object.create(null)); } -/** - * Returns a new object that has all values of {{obj}} - * plus those from {{defaults}}. - */ -export function withDefaults(obj: T, defaults: T): T { - return mixin(clone(defaults), obj || {}); -} - export function equals(one: any, other: any): boolean { if (one === other) { return true; From 7eebddd4549974866eba66767916eea8a781f995 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 11 May 2016 10:52:39 +0200 Subject: [PATCH 142/297] ai - make sure not lose default data --- src/vs/base/parts/ai/node/ai.ipc.ts | 4 +-- src/vs/base/parts/ai/node/aiAdapter.ts | 29 ++++++++----------- .../test/node/aiAdapter/aiAdapter.test.ts | 2 +- 3 files changed, 15 insertions(+), 20 deletions(-) diff --git a/src/vs/base/parts/ai/node/ai.ipc.ts b/src/vs/base/parts/ai/node/ai.ipc.ts index 639c625ccda..bb76d301788 100644 --- a/src/vs/base/parts/ai/node/ai.ipc.ts +++ b/src/vs/base/parts/ai/node/ai.ipc.ts @@ -9,8 +9,8 @@ import {TPromise} from 'vs/base/common/winjs.base'; import {IChannel} from 'vs/base/parts/ipc/common/ipc'; export interface IAIChannel extends IChannel { - call(command: 'create', data: { key: string; eventPrefix: string; data: any; }): TPromise; - call(command: 'log', data: { handle: number; eventName: string; data: any; }): TPromise; + call(command: 'create', data: { key: string; eventPrefix: string; data: { [k: string]: any }; }): TPromise; + call(command: 'log', data: { handle: number; eventName: string; data: { [k: string]: any }; }): TPromise; call(command: 'dispose', data: { handle: number; }): TPromise; call(command: string, arg: any): TPromise; } diff --git a/src/vs/base/parts/ai/node/aiAdapter.ts b/src/vs/base/parts/ai/node/aiAdapter.ts index 2d1615678c5..1060c2004cf 100644 --- a/src/vs/base/parts/ai/node/aiAdapter.ts +++ b/src/vs/base/parts/ai/node/aiAdapter.ts @@ -54,16 +54,17 @@ export class AIAdapter { constructor( private _eventPrefix: string, - private _additionalDataToLog: () => TPromise<{ [key: string]: any }>, - clientFactoryOrAiKey: (() => typeof appInsights.client) | string // allow factory function for testing + private _defaultData: { [key: string]: any }, + aiKeyOrClientFactory: string | (() => typeof appInsights.client) // allow factory function for testing ) { - if (!this._additionalDataToLog) { - this._additionalDataToLog = () => TPromise.as(undefined); + if (!this._defaultData) { + this._defaultData = Object.create(null); } - if (typeof clientFactoryOrAiKey === 'string') { - this._aiClient = AI.getClient(clientFactoryOrAiKey); - } else if (typeof clientFactoryOrAiKey === 'function') { - this._aiClient = clientFactoryOrAiKey(); + + if (typeof aiKeyOrClientFactory === 'string') { + this._aiClient = AI.getClient(aiKeyOrClientFactory); + } else if (typeof aiKeyOrClientFactory === 'function') { + this._aiClient = aiKeyOrClientFactory(); } } @@ -133,15 +134,9 @@ export class AIAdapter { if (!this._aiClient) { return; } - this._additionalDataToLog().then(additionalData => { - return mixin(data, additionalData); - }, err => { - console.error(err); // ignore? - return data; - }).done(data => { - let {properties, measurements} = AIAdapter._getData(data); - this._aiClient.trackEvent(this._eventPrefix + '/' + eventName, properties, measurements); - }); + data = mixin(data, this._defaultData); + let {properties, measurements} = AIAdapter._getData(data); + this._aiClient.trackEvent(this._eventPrefix + '/' + eventName, properties, measurements); } public dispose(): TPromise { diff --git a/src/vs/base/test/node/aiAdapter/aiAdapter.test.ts b/src/vs/base/test/node/aiAdapter/aiAdapter.test.ts index bbf1b19ce74..f38204af9ec 100644 --- a/src/vs/base/test/node/aiAdapter/aiAdapter.test.ts +++ b/src/vs/base/test/node/aiAdapter/aiAdapter.test.ts @@ -62,7 +62,7 @@ suite('AIAdapter', () => { }); test('addional data', () => { - adapter = new AIAdapter(prefix, () => TPromise.as({ first: '1st', second: 2, third: true }), () => appInsightsMock); + adapter = new AIAdapter(prefix, { first: '1st', second: 2, third: true }, () => appInsightsMock); adapter.log('testEvent'); assert.equal(appInsightsMock.events.length, 1); From eff2646ca7b7cb5944b4205db1820cea49092b20 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 11 May 2016 10:53:22 +0200 Subject: [PATCH 143/297] :lipstick: unused import --- src/vs/base/test/node/aiAdapter/aiAdapter.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/vs/base/test/node/aiAdapter/aiAdapter.test.ts b/src/vs/base/test/node/aiAdapter/aiAdapter.test.ts index f38204af9ec..e0cb1917f10 100644 --- a/src/vs/base/test/node/aiAdapter/aiAdapter.test.ts +++ b/src/vs/base/test/node/aiAdapter/aiAdapter.test.ts @@ -5,7 +5,6 @@ 'use strict'; import * as assert from 'assert'; -import {TPromise} from 'vs/base/common/winjs.base'; import {AIAdapter} from 'vs/base/parts/ai/node/aiAdapter'; interface IAppInsightsEvent { From ce3fb81e221457b0f8b404ac04f90a0fcac38d58 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 11 May 2016 15:23:55 +0200 Subject: [PATCH 144/297] quick open: do not handle Enter on key_down, otherwise it bubbles to editor on key_up --- .../quickopen/browser/quickOpenWidget.ts | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/vs/base/parts/quickopen/browser/quickOpenWidget.ts b/src/vs/base/parts/quickopen/browser/quickOpenWidget.ts index 97500cc6efb..4527892af4e 100644 --- a/src/vs/base/parts/quickopen/browser/quickOpenWidget.ts +++ b/src/vs/base/parts/quickopen/browser/quickOpenWidget.ts @@ -111,7 +111,7 @@ export class QuickOpenWidget implements IModelProvider { this.builder = $().div((div: Builder) => { // Eventing - div.on(DOM.EventType.KEY_DOWN, (e: KeyboardEvent) => { + div.on(DOM.EventType.KEY_UP, (e: KeyboardEvent) => { let keyboardEvent: StandardKeyboardEvent = new StandardKeyboardEvent(e); if (keyboardEvent.keyCode === KeyCode.Escape) { DOM.EventHelper.stop(e, true); @@ -141,6 +141,7 @@ export class QuickOpenWidget implements IModelProvider { this.inputElement.setAttribute('aria-haspopup', 'false'); this.inputElement.setAttribute('aria-autocomplete', 'list'); + // Listen to some keys on key-down for faster type feedback DOM.addDisposableListener(this.inputBox.inputElement, DOM.EventType.KEY_DOWN, (e: KeyboardEvent) => { let keyboardEvent: StandardKeyboardEvent = new StandardKeyboardEvent(e); @@ -156,8 +157,17 @@ export class QuickOpenWidget implements IModelProvider { this.navigateInTree(keyboardEvent.keyCode, keyboardEvent.shiftKey); } + // Bug in IE 9: onInput is not fired for Backspace or Delete keys + else if (browser.isIE9 && (keyboardEvent.keyCode === KeyCode.Backspace || keyboardEvent.keyCode === KeyCode.Delete)) { + this.onType(); + } + }); + + DOM.addDisposableListener(this.inputBox.inputElement, DOM.EventType.KEY_UP, (e: KeyboardEvent) => { + let keyboardEvent: StandardKeyboardEvent = new StandardKeyboardEvent(e); + // Select element on Enter - else if (keyboardEvent.keyCode === KeyCode.Enter) { + if (keyboardEvent.keyCode === KeyCode.Enter) { DOM.EventHelper.stop(e, true); let focus = this.tree.getFocus(); @@ -165,11 +175,6 @@ export class QuickOpenWidget implements IModelProvider { this.elementSelected(focus, e); } } - - // Bug in IE 9: onInput is not fired for Backspace or Delete keys - else if (browser.isIE9 && (keyboardEvent.keyCode === KeyCode.Backspace || keyboardEvent.keyCode === KeyCode.Delete)) { - this.onType(); - } }); DOM.addDisposableListener(this.inputBox.inputElement, DOM.EventType.INPUT, (e: Event) => { From 5c37571f631f238b1a73622db0617ad93bc3915d Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 11 May 2016 16:26:32 +0200 Subject: [PATCH 145/297] startup perf, take finding git off the critical path --- .../workbench/parts/git/electron-browser/electronGitService.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/parts/git/electron-browser/electronGitService.ts b/src/vs/workbench/parts/git/electron-browser/electronGitService.ts index dbe626937f7..702e4db62e2 100644 --- a/src/vs/workbench/parts/git/electron-browser/electronGitService.ts +++ b/src/vs/workbench/parts/git/electron-browser/electronGitService.ts @@ -157,7 +157,8 @@ export class ElectronGitService extends GitService { const encoding = (conf.files && conf.files.encoding) || 'utf8'; const workspaceRoot = workspace.resource.fsPath; - const promise = findGit(gitPath) + const promise = TPromise.timeout(0) // free event loop cos finding git costs + .then(() => findGit(gitPath)) .then(({ path, version }) => { const client = new Client( URI.parse(require.toUrl('bootstrap')).fsPath, From 79280a1989aab9217311838f0d0f0839c8da9709 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 11 May 2016 17:07:53 +0200 Subject: [PATCH 146/297] :racehorse: - remove 'fork' from the critical (startup) path by using setImmediate --- src/vs/base/parts/ipc/node/ipc.cp.ts | 128 ++++++++++++++------------- 1 file changed, 67 insertions(+), 61 deletions(-) diff --git a/src/vs/base/parts/ipc/node/ipc.cp.ts b/src/vs/base/parts/ipc/node/ipc.cp.ts index a525d878dc2..7116780e97a 100644 --- a/src/vs/base/parts/ipc/node/ipc.cp.ts +++ b/src/vs/base/parts/ipc/node/ipc.cp.ts @@ -5,7 +5,7 @@ import { ChildProcess, fork } from 'child_process'; import { IDisposable } from 'vs/base/common/lifecycle'; -import { Promise} from 'vs/base/common/winjs.base'; +import { TPromise, Promise} from 'vs/base/common/winjs.base'; import { Delayer } from 'vs/base/common/async'; import { clone, assign } from 'vs/base/common/objects'; import { Server as IPCServer, Client as IPCClient, IClient, IChannel } from 'vs/base/parts/ipc/common/ipc'; @@ -58,15 +58,13 @@ export class Client implements IClient, IDisposable { private disposeDelayer: Delayer; private activeRequests: Promise[]; - private child: ChildProcess; - private _client: IPCClient; - private channels: { [name: string]: IChannel }; + private _client: TPromise<[IPCClient, ChildProcess]>; + private channels: { [name: string]: TPromise }; constructor(private modulePath: string, private options: IIPCOptions) { const timeout = options && options.timeout ? options.timeout : 60000; this.disposeDelayer = new Delayer(timeout); this.activeRequests = []; - this.child = null; this._client = null; this.channels = Object.create(null); } @@ -79,8 +77,8 @@ export class Client implements IClient, IDisposable { protected request(channelName: string, name: string, arg: any): Promise { this.disposeDelayer.cancel(); - const channel = this.channels[channelName] || (this.channels[channelName] = this.client.getChannel(channelName)); - const request: Promise = channel.call(name, arg); + const channel = this.channels[channelName] || (this.channels[channelName] = this.client.then(value => value[0].getChannel(channelName))); + const request: Promise = channel.then(channel => channel.call(name, arg)); // Progress doesn't propagate across 'then', we need to create a promise wrapper const result = new Promise((c, e, p) => { @@ -98,72 +96,78 @@ export class Client implements IClient, IDisposable { return result; } - private get client(): IPCClient { + private get client(): TPromise<[IPCClient, ChildProcess]> { if (!this._client) { - const args = this.options && this.options.args ? this.options.args : []; - let forkOpts:any = undefined; + this._client = TPromise.timeout(0).then(() => { // since fork is expensive and we end up here often + // during startup, we do a timeout(0) which is a setImmediate - if (this.options) { - forkOpts = Object.create(null); + const args = this.options && this.options.args ? this.options.args : []; + let forkOpts:any = undefined; - if (this.options.env) { - forkOpts.env = assign(clone(process.env), this.options.env); + if (this.options) { + forkOpts = Object.create(null); + + if (this.options.env) { + forkOpts.env = assign(clone(process.env), this.options.env); + } + + if (typeof this.options.debug === 'number') { + forkOpts.execArgv = ['--nolazy', '--debug=' + this.options.debug]; + } + + if (typeof this.options.debugBrk === 'number') { + forkOpts.execArgv = ['--nolazy', '--debug-brk=' + this.options.debugBrk]; + } } - if (typeof this.options.debug === 'number') { - forkOpts.execArgv = ['--nolazy', '--debug=' + this.options.debug]; - } + const child = fork(this.modulePath, args, forkOpts); + const client = new IPCClient({ + send: r => child && child.connected && child.send(r), + onMessage: cb => { + child.on('message', (msg) => { - if (typeof this.options.debugBrk === 'number') { - forkOpts.execArgv = ['--nolazy', '--debug-brk=' + this.options.debugBrk]; - } - } + // Handle console logs specially + if (msg && msg.type === '__$console') { + let args = ['%c[IPC Library: ' + this.options.serverName + ']', 'color: darkgreen']; + try { + const parsed = JSON.parse(msg.arguments); + args = args.concat(Object.getOwnPropertyNames(parsed).map(o => parsed[o])); + } catch (error) { + args.push(msg.arguments); + } - this.child = fork(this.modulePath, args, forkOpts); - this._client = new IPCClient({ - send: r => this.child && this.child.connected && this.child.send(r), - onMessage: cb => { - this.child.on('message', (msg) => { - - // Handle console logs specially - if (msg && msg.type === '__$console') { - let args = ['%c[IPC Library: ' + this.options.serverName + ']', 'color: darkgreen']; - try { - const parsed = JSON.parse(msg.arguments); - args = args.concat(Object.getOwnPropertyNames(parsed).map(o => parsed[o])); - } catch (error) { - args.push(msg.arguments); + console[msg.severity].apply(console, args); } - console[msg.severity].apply(console, args); - } + // Anything else goes to the outside + else { + cb(msg); + } + }); + } + }); - // Anything else goes to the outside - else { - cb(msg); - } - }); - } - }); + const onExit = () => this.disposeClient(); + process.once('exit', onExit); - const onExit = () => this.disposeClient(); - process.once('exit', onExit); + child.on('error', err => console.warn('IPC "' + this.options.serverName + '" errored with ' + err)); - this.child.on('error', err => console.warn('IPC "' + this.options.serverName + '" errored with ' + err)); + child.on('exit', (code: any, signal: any) => { + process.removeListener('exit', onExit); - this.child.on('exit', (code: any, signal: any) => { - process.removeListener('exit', onExit); + if (this.activeRequests) { + this.activeRequests.forEach(req => req.cancel()); + this.activeRequests = []; + } - if (this.activeRequests) { - this.activeRequests.forEach(req => req.cancel()); - this.activeRequests = []; - } + if (code && signal !== 'SIGTERM') { + console.warn('IPC "' + this.options.serverName + '" crashed with exit code ' + code); + this.disposeDelayer.cancel(); + this.disposeClient(); + } + }); - if (code && signal !== 'SIGTERM') { - console.warn('IPC "' + this.options.serverName + '" crashed with exit code ' + code); - this.disposeDelayer.cancel(); - this.disposeClient(); - } + return [client, child]; }); } @@ -172,10 +176,12 @@ export class Client implements IClient, IDisposable { private disposeClient() { if (this._client) { - this.child.kill(); - this.child = null; - this._client = null; + this._client.done(value => { + let [, child] = value; + child.kill(); + }); this.channels = Object.create(null); + this._client = null; } } From cf48c4eb7d4416313c77b520243fa409b40beb72 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Thu, 12 May 2016 00:15:42 -0700 Subject: [PATCH 147/297] Fix --uninstall-extension typo in --help Fixes #6266 --- src/vs/code/node/argv.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/code/node/argv.ts b/src/vs/code/node/argv.ts index 49121642375..85beec2aa4d 100644 --- a/src/vs/code/node/argv.ts +++ b/src/vs/code/node/argv.ts @@ -99,5 +99,5 @@ ${ indent }-w, --wait Wait for the window to be closed before returni ${ indent }--list-extensions List the installed extensions. ${ indent }--install-extension ${ indent } Installs an extension. -${ indent }--list-extensions +${ indent }--uninstall-extension ${ indent } Uninstalls an extension.`; From 87fb437eb88ff9748f31f2b016d931363b7007ea Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Thu, 12 May 2016 09:29:38 +0200 Subject: [PATCH 148/297] :lipstick: remove unused code --- .../contrib/codelens/browser/codelens.ts | 30 ++++--------------- 1 file changed, 6 insertions(+), 24 deletions(-) diff --git a/src/vs/editor/contrib/codelens/browser/codelens.ts b/src/vs/editor/contrib/codelens/browser/codelens.ts index ee4f98592e3..9956057da14 100644 --- a/src/vs/editor/contrib/codelens/browser/codelens.ts +++ b/src/vs/editor/contrib/codelens/browser/codelens.ts @@ -13,7 +13,6 @@ import Severity from 'vs/base/common/severity'; import {format} from 'vs/base/common/strings'; import {TPromise} from 'vs/base/common/winjs.base'; import * as dom from 'vs/base/browser/dom'; -import {IConfigurationService} from 'vs/platform/configuration/common/configuration'; import {IKeybindingService} from 'vs/platform/keybinding/common/keybindingService'; import {IMessageService} from 'vs/platform/message/common/message'; import {Range} from 'vs/editor/common/core/range'; @@ -340,45 +339,28 @@ export class CodeLensContribution implements editorCommon.IEditorContribution { public static ID: string = 'css.editor.codeLens'; - private static INSTANCE_COUNT: number = 0; - - private _instanceCount: number; - private _editor: editorBrowser.ICodeEditor; - private _modelService: IModelService; private _isEnabled: boolean; private _globalToDispose: IDisposable[]; - private _localToDispose: IDisposable[]; private _lenses: CodeLens[]; private _currentFindCodeLensSymbolsPromise: TPromise; private _modelChangeCounter: number; - private _configurationService: IConfigurationService; - private _keybindingService: IKeybindingService; - private _messageService: IMessageService; - private _codeLenseDisabledByMode: boolean; - private _currentFindOccPromise: TPromise; - constructor(editor: editorBrowser.ICodeEditor, @IModelService modelService: IModelService, - @IConfigurationService configurationService: IConfigurationService, - @IKeybindingService keybindingService: IKeybindingService, - @IMessageService messageService: IMessageService) { - - this._instanceCount = (++CodeLensContribution.INSTANCE_COUNT); - this._editor = editor; - this._modelService = modelService; + constructor( + private _editor: editorBrowser.ICodeEditor, + @IModelService private _modelService: IModelService, + @IKeybindingService private _keybindingService: IKeybindingService, + @IMessageService private _messageService: IMessageService + ) { this._isEnabled = this._editor.getConfiguration().contribInfo.referenceInfos; - this._configurationService = configurationService; - this._keybindingService = keybindingService; - this._messageService = messageService; this._globalToDispose = []; this._localToDispose = []; this._lenses = []; this._currentFindCodeLensSymbolsPromise = null; this._modelChangeCounter = 0; - this._codeLenseDisabledByMode = true; this._globalToDispose.push(this._editor.addListener2(editorCommon.EventType.ModelChanged, () => this.onModelChange())); this._globalToDispose.push(this._editor.addListener2(editorCommon.EventType.ModelModeChanged, () => this.onModelChange())); From b633941dfe9bd0f5fa8042a581866bc9207c3bc6 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Thu, 12 May 2016 01:29:45 -0700 Subject: [PATCH 149/297] Fix comment typo --- src/vs/workbench/parts/emmet/node/editorAccessor.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/parts/emmet/node/editorAccessor.ts b/src/vs/workbench/parts/emmet/node/editorAccessor.ts index b392b347746..b979cc74901 100644 --- a/src/vs/workbench/parts/emmet/node/editorAccessor.ts +++ b/src/vs/workbench/parts/emmet/node/editorAccessor.ts @@ -121,7 +121,7 @@ export class EditorAccessor implements emmet.Editor { if (/\b(typescriptreact|javascriptreact)\b/.test(syntax)) { // treat like tsx like jsx return 'jsx'; } - if (syntax === 'sass') { // sass is really sccs... map it to scss + if (syntax === 'sass') { // sass is really scss... map it to scss return'scss'; } if (syntax === 'stylus') { // map stylus to css From 6dcfa2e9d1f380eee3a53987c0e358fce2cb9edc Mon Sep 17 00:00:00 2001 From: Dirk Baeumer Date: Thu, 12 May 2016 11:52:33 +0200 Subject: [PATCH 150/297] Adding line break to output message --- extensions/typescript/src/typescriptServiceClient.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/typescript/src/typescriptServiceClient.ts b/extensions/typescript/src/typescriptServiceClient.ts index bb4c5c6dc6f..bcabff855ed 100644 --- a/extensions/typescript/src/typescriptServiceClient.ts +++ b/extensions/typescript/src/typescriptServiceClient.ts @@ -383,7 +383,7 @@ export default class TypeScriptServiceClient implements ITypescriptServiceClient } } if (this.trace !== Trace.Off) { - this.output.append(`TypeScript Service: tried to cancel request with sequence number ${seq}. But request got already delivered.`); + this.output.append(`TypeScript Service: tried to cancel request with sequence number ${seq}. But request got already delivered.\n`); } return false; } From e2da5725c1bc8d1e63a733407b509a6668040c11 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Thu, 12 May 2016 12:18:15 +0200 Subject: [PATCH 151/297] move webview into its own source file, use css variables for webview default styles, #5737 --- .../parts/html/browser/htmlPreviewPart.ts | 167 +---------------- .../workbench/parts/html/browser/webview.ts | 172 ++++++++++++++++++ 2 files changed, 177 insertions(+), 162 deletions(-) create mode 100644 src/vs/workbench/parts/html/browser/webview.ts diff --git a/src/vs/workbench/parts/html/browser/htmlPreviewPart.ts b/src/vs/workbench/parts/html/browser/htmlPreviewPart.ts index b7141384c0a..aed174f58ad 100644 --- a/src/vs/workbench/parts/html/browser/htmlPreviewPart.ts +++ b/src/vs/workbench/parts/html/browser/htmlPreviewPart.ts @@ -5,180 +5,23 @@ 'use strict'; -import 'vs/text!./webview.html'; import {localize} from 'vs/nls'; import URI from 'vs/base/common/uri'; import {TPromise} from 'vs/base/common/winjs.base'; import {IModel, EventType} from 'vs/editor/common/editorCommon'; import {Dimension, Builder} from 'vs/base/browser/builder'; -import {empty as EmptyDisposable, IDisposable, dispose} from 'vs/base/common/lifecycle'; -import {addDisposableListener, addClass} from 'vs/base/browser/dom'; +import {empty as EmptyDisposable} from 'vs/base/common/lifecycle'; import {EditorOptions, EditorInput} from 'vs/workbench/common/editor'; import {BaseEditor} from 'vs/workbench/browser/parts/editor/baseEditor'; import {Position} from 'vs/platform/editor/common/editor'; import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry'; import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace'; -import {isLightTheme} from 'vs/platform/theme/common/themes'; import {IWorkbenchEditorService} from 'vs/workbench/services/editor/common/editorService'; import {BaseTextEditorModel} from 'vs/workbench/common/editor/textEditorModel'; import {HtmlInput} from 'vs/workbench/parts/html/common/htmlInput'; import {IThemeService} from 'vs/workbench/services/themes/common/themeService'; -import {KeybindingsRegistry} from 'vs/platform/keybinding/common/keybindingsRegistry'; import {IOpenerService} from 'vs/platform/opener/common/opener'; - -KeybindingsRegistry.registerCommandDesc({ - id: '_webview.openDevTools', - when: null, - weight: KeybindingsRegistry.WEIGHT.workbenchContrib(0), - primary: null, - handler() { - const elements = document.querySelectorAll('webview.ready'); - for (let i = 0; i < elements.length; i++) { - try { - (elements.item(i)).openDevTools(); - } catch (e) { - console.error(e); - } - } - } -}); - -declare interface Webview extends HTMLElement { - src: string; - autoSize: 'on'; - nodeintegration: 'on'; - disablewebsecurity: 'on'; - - getURL(): string; - getTitle(): string; - executeJavaScript(code: string, userGesture?: boolean, callback?: (result: any) => any); - send(channel: string, ...args: any[]); - openDevTools(): any; - closeDevTools(): any; -} - -class ManagedWebview { - - private _webview: Webview; - private _ready: TPromise; - private _disposables: IDisposable[]; - - constructor(private _parent: HTMLElement, private _styleElement: Element, onDidClickLink:(uri:URI)=>any) { - this._webview = document.createElement('webview'); - - this._webview.style.width = '100%'; - this._webview.style.height = '100%'; - this._webview.autoSize = 'on'; - this._webview.nodeintegration = 'on'; - this._webview.src = require.toUrl('./webview.html'); - - this._ready = new TPromise(resolve => { - const subscription = addDisposableListener(this._webview, 'ipc-message', (event) => { - if (event.channel === 'webview-ready') { - - // console.info('[PID Webview] ' + event.args[0]); - addClass(this._webview, 'ready'); // can be found by debug command - - subscription.dispose(); - resolve(this); - } - }); - }); - - this._disposables = [ - addDisposableListener(this._webview, 'console-message', function (e: { level: number; message: string; line: number; sourceId: string; }) { - console.log(`[Embedded Page] ${e.message}`); - }), - addDisposableListener(this._webview, 'crashed', function () { - console.error('embedded page crashed'); - }), - addDisposableListener(this._webview, 'ipc-message', (event) => { - if (event.channel === 'did-click-link') { - let [uri] = event.args; - onDidClickLink(URI.parse(uri)); - } - }) - ]; - - this._parent.appendChild(this._webview); - } - - dispose(): void { - this._disposables = dispose(this._disposables); - this._webview.parentElement.removeChild(this._webview); - } - - private _send(channel: string, ...args: any[]): void { - this._ready - .then(() => this._webview.send(channel, ...args)) - .done(void 0, console.error); - } - - set contents(value: string[]) { - this._send('content', value); - } - - set baseUrl(value: string) { - this._send('baseUrl', value); - } - - focus(): void { - this._send('focus'); - } - - style(themeId: string): void { - const {color, backgroundColor, fontFamily, fontSize} = window.getComputedStyle(this._styleElement); - - let value = ` - body { - margin: 0; - } - * { - color: ${color}; - background-color: ${backgroundColor}; - font-family: ${fontFamily}; - font-size: ${fontSize}; - } - img { - max-width: 100%; - max-height: 100%; - } - a:focus, - input:focus, - select:focus, - textarea:focus { - outline: 1px solid -webkit-focus-ring-color; - outline-offset: -1px; - } - ::-webkit-scrollbar { - width: 14px; - height: 10px; - } - ::-webkit-scrollbar-thumb:hover { - background-color: rgba(100, 100, 100, 0.7); - }`; - - if (isLightTheme(themeId)) { - value += ` - ::-webkit-scrollbar-thumb { - background-color: rgba(100, 100, 100, 0.4); - } - ::-webkit-scrollbar-thumb:active { - background-color: rgba(0, 0, 0, 0.6); - }`; - } else { - value += ` - ::-webkit-scrollbar-thumb { - background-color: rgba(121, 121, 121, 0.4); - } - ::-webkit-scrollbar-thumb:active { - background-color: rgba(85, 85, 85, 0.8); - }`; - } - - this._send('styles', value); - } -} +import Webview from './webview'; /** * An implementation of editor for showing HTML content in an IFrame by leveraging the IFrameEditorInput. @@ -190,7 +33,7 @@ export class HtmlPreviewPart extends BaseEditor { private _editorService: IWorkbenchEditorService; private _themeService: IThemeService; private _openerService: IOpenerService; - private _webview: ManagedWebview; + private _webview: Webview; private _container: HTMLDivElement; private _baseUrl: URI; @@ -234,9 +77,9 @@ export class HtmlPreviewPart extends BaseEditor { parent.getHTMLElement().appendChild(this._container); } - private get webview(): ManagedWebview { + private get webview(): Webview { if (!this._webview) { - this._webview = new ManagedWebview(this._container, + this._webview = new Webview(this._container, document.querySelector('.monaco-editor-background'), uri => this._openerService.open(uri)); diff --git a/src/vs/workbench/parts/html/browser/webview.ts b/src/vs/workbench/parts/html/browser/webview.ts new file mode 100644 index 00000000000..fa2d33cd25d --- /dev/null +++ b/src/vs/workbench/parts/html/browser/webview.ts @@ -0,0 +1,172 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import 'vs/text!./webview.html'; +import URI from 'vs/base/common/uri'; +import {TPromise} from 'vs/base/common/winjs.base'; +import {IDisposable, dispose} from 'vs/base/common/lifecycle'; +import {addDisposableListener, addClass} from 'vs/base/browser/dom'; +import {isLightTheme} from 'vs/platform/theme/common/themes'; +import {KeybindingsRegistry} from 'vs/platform/keybinding/common/keybindingsRegistry'; + +declare interface WebviewElement extends HTMLElement { + src: string; + autoSize: 'on'; + nodeintegration: 'on'; + disablewebsecurity: 'on'; + + getURL(): string; + getTitle(): string; + executeJavaScript(code: string, userGesture?: boolean, callback?: (result: any) => any); + send(channel: string, ...args: any[]); + openDevTools(): any; + closeDevTools(): any; +} + +KeybindingsRegistry.registerCommandDesc({ + id: '_webview.openDevTools', + when: null, + weight: KeybindingsRegistry.WEIGHT.workbenchContrib(0), + primary: null, + handler() { + const elements = document.querySelectorAll('webview.ready'); + for (let i = 0; i < elements.length; i++) { + try { + (elements.item(i)).openDevTools(); + } catch (e) { + console.error(e); + } + } + } +}); + +export default class Webview { + + private _webview: WebviewElement; + private _ready: TPromise; + private _disposables: IDisposable[]; + + constructor(private _parent: HTMLElement, private _styleElement: Element, onDidClickLink:(uri:URI)=>any) { + this._webview = document.createElement('webview'); + + this._webview.style.width = '100%'; + this._webview.style.height = '100%'; + this._webview.autoSize = 'on'; + this._webview.nodeintegration = 'on'; + this._webview.src = require.toUrl('./webview.html'); + + this._ready = new TPromise(resolve => { + const subscription = addDisposableListener(this._webview, 'ipc-message', (event) => { + if (event.channel === 'webview-ready') { + + // console.info('[PID Webview] ' + event.args[0]); + addClass(this._webview, 'ready'); // can be found by debug command + + subscription.dispose(); + resolve(this); + } + }); + }); + + this._disposables = [ + addDisposableListener(this._webview, 'console-message', function (e: { level: number; message: string; line: number; sourceId: string; }) { + console.log(`[Embedded Page] ${e.message}`); + }), + addDisposableListener(this._webview, 'crashed', function () { + console.error('embedded page crashed'); + }), + addDisposableListener(this._webview, 'ipc-message', (event) => { + if (event.channel === 'did-click-link') { + let [uri] = event.args; + onDidClickLink(URI.parse(uri)); + } + }) + ]; + + this._parent.appendChild(this._webview); + } + + dispose(): void { + this._disposables = dispose(this._disposables); + this._webview.parentElement.removeChild(this._webview); + } + + private _send(channel: string, ...args: any[]): void { + this._ready + .then(() => this._webview.send(channel, ...args)) + .done(void 0, console.error); + } + + set contents(value: string[]) { + this._send('content', value); + } + + set baseUrl(value: string) { + this._send('baseUrl', value); + } + + focus(): void { + this._send('focus'); + } + + style(themeId: string): void { + const {color, backgroundColor, fontFamily, fontSize} = window.getComputedStyle(this._styleElement); + + let value = ` + :root { + --background-color: ${backgroundColor}; + --color: ${color}; + --font-family: ${fontFamily}; + --font-size: ${fontSize}; + } + body { + margin: 0; + background-color: var(--background-color); + color: var(--color); + font-family: var(--font-family); + font-size: var(--font-size); + } + img { + max-width: 100%; + max-height: 100%; + } + a:focus, + input:focus, + select:focus, + textarea:focus { + outline: 1px solid -webkit-focus-ring-color; + outline-offset: -1px; + } + ::-webkit-scrollbar { + width: 14px; + height: 10px; + } + ::-webkit-scrollbar-thumb:hover { + background-color: rgba(100, 100, 100, 0.7); + }`; + + if (isLightTheme(themeId)) { + value += ` + ::-webkit-scrollbar-thumb { + background-color: rgba(100, 100, 100, 0.4); + } + ::-webkit-scrollbar-thumb:active { + background-color: rgba(0, 0, 0, 0.6); + }`; + } else { + value += ` + ::-webkit-scrollbar-thumb { + background-color: rgba(121, 121, 121, 0.4); + } + ::-webkit-scrollbar-thumb:active { + background-color: rgba(85, 85, 85, 0.8); + }`; + } + + this._send('styles', value); + } +} From aaa65451f6f2d6de290ee3cb1c8ce1f2def7a52a Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Thu, 12 May 2016 12:48:10 +0200 Subject: [PATCH 152/297] set focus on iframe window and on webview, fixes #5070 --- src/vs/workbench/parts/html/browser/webview.html | 2 +- src/vs/workbench/parts/html/browser/webview.ts | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/parts/html/browser/webview.html b/src/vs/workbench/parts/html/browser/webview.html index f3865d0b41a..4bf4659054a 100644 --- a/src/vs/workbench/parts/html/browser/webview.html +++ b/src/vs/workbench/parts/html/browser/webview.html @@ -34,7 +34,7 @@ // propagate focus ipcRenderer.on('focus', function() { - target.contentDocument.body.focus(); + target.contentWindow.focus(); }); // update iframe-contents diff --git a/src/vs/workbench/parts/html/browser/webview.ts b/src/vs/workbench/parts/html/browser/webview.ts index fa2d33cd25d..dc3b2b598e5 100644 --- a/src/vs/workbench/parts/html/browser/webview.ts +++ b/src/vs/workbench/parts/html/browser/webview.ts @@ -110,6 +110,7 @@ export default class Webview { } focus(): void { + this._webview.focus(); this._send('focus'); } From 41467b74b7e486f3a5857d3cc0ab15d85a2b7a84 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Thu, 12 May 2016 12:53:21 +0200 Subject: [PATCH 153/297] use padding-left of 20px for preview part, fixes #5883 --- src/vs/workbench/parts/html/browser/htmlPreviewPart.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vs/workbench/parts/html/browser/htmlPreviewPart.ts b/src/vs/workbench/parts/html/browser/htmlPreviewPart.ts index aed174f58ad..5fe7b97092f 100644 --- a/src/vs/workbench/parts/html/browser/htmlPreviewPart.ts +++ b/src/vs/workbench/parts/html/browser/htmlPreviewPart.ts @@ -74,6 +74,7 @@ export class HtmlPreviewPart extends BaseEditor { public createEditor(parent: Builder): void { this._container = document.createElement('div'); + this._container.style.paddingLeft = '20px'; parent.getHTMLElement().appendChild(this._container); } From ba09fd7fad9e3add53f4ac633943e1b2b56a51a0 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Thu, 12 May 2016 17:46:14 +0200 Subject: [PATCH 154/297] use 'property' instead of 'text' when CompletionItem define no kind --- src/vs/workbench/api/node/extHostTypeConverters.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/api/node/extHostTypeConverters.ts b/src/vs/workbench/api/node/extHostTypeConverters.ts index c534adeb3ff..82350281925 100644 --- a/src/vs/workbench/api/node/extHostTypeConverters.ts +++ b/src/vs/workbench/api/node/extHostTypeConverters.ts @@ -376,12 +376,12 @@ export const CompletionItemKind = { case types.CompletionItemKind.File: return 'file'; case types.CompletionItemKind.Reference: return 'reference'; } - return 'text'; + return 'property'; }, to(type: modes.SuggestionType): types.CompletionItemKind { if (!type) { - return types.CompletionItemKind.Text; + return types.CompletionItemKind.Property; } else { return types.CompletionItemKind[type.charAt(0).toUpperCase() + type.substr(1)]; } From bbe22d2072a0c7475e182dc719586cc37c17c624 Mon Sep 17 00:00:00 2001 From: isidor Date: Thu, 12 May 2016 18:54:10 +0200 Subject: [PATCH 155/297] debug: handle php one thread stop behavior as a special case not as a general rule fixes #6304 --- .../parts/debug/electron-browser/debugService.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/parts/debug/electron-browser/debugService.ts b/src/vs/workbench/parts/debug/electron-browser/debugService.ts index 8a61b2e3e4e..30c5fc809eb 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugService.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugService.ts @@ -867,11 +867,11 @@ export class DebugService implements debug.IDebugService { toDispose.dispose(); if (!cancelTransitionToRunningState) { aria.status(nls.localize('debuggingContinued', "Debugging continued.")); - // TODO@Isidor temporary workaround for #5835 - if (this.session && strings.equalsIgnoreCase(this.session.configuration.type, 'go')) { - this.model.clearThreads(false); - } else { + // TODO@Isidor temporary workaround for #1703 + if (this.session && strings.equalsIgnoreCase(this.session.configuration.type, 'php')) { this.model.clearThreads(false, threadId); + } else { + this.model.clearThreads(false); } // Get a top stack frame of a stopped thread if there is any. From a6a9409897000e375cd78f77acf58b1b09a6f6d7 Mon Sep 17 00:00:00 2001 From: Andre Weinand Date: Thu, 12 May 2016 19:33:20 +0200 Subject: [PATCH 156/297] update node-debug --- extensions/node-debug/node-debug.azure.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/node-debug/node-debug.azure.json b/extensions/node-debug/node-debug.azure.json index b4b4b70c524..2e250bd46fe 100644 --- a/extensions/node-debug/node-debug.azure.json +++ b/extensions/node-debug/node-debug.azure.json @@ -1,6 +1,6 @@ { "account": "monacobuild", "container": "debuggers", - "zip": "161b5f4/node-debug.zip", + "zip": "a2391c1/node-debug.zip", "output": "" } From 186094c7240ee1721352e3137c63906fb179dd5e Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Thu, 12 May 2016 10:47:01 -0700 Subject: [PATCH 157/297] Use correct path on Windows --- src/vs/workbench/parts/terminal/node/terminalPanel.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/parts/terminal/node/terminalPanel.ts b/src/vs/workbench/parts/terminal/node/terminalPanel.ts index f9d134a5fd8..93ee7cc86eb 100644 --- a/src/vs/workbench/parts/terminal/node/terminalPanel.ts +++ b/src/vs/workbench/parts/terminal/node/terminalPanel.ts @@ -57,7 +57,7 @@ export class TerminalPanel extends Panel { name: fs.existsSync('/usr/share/terminfo/x/xterm-256color') ? 'xterm-256color' : 'xterm', cols: 80, rows: 6, - cwd: this.contextService.getWorkspace() ? this.contextService.getWorkspace().resource.path : process.env.HOME + cwd: this.contextService.getWorkspace() ? this.contextService.getWorkspace().resource.fsPath : process.env.HOME }); this.terminalDomElement = document.createElement('div'); this.parentDomElement.classList.add('integrated-terminal'); From 75ec70cc72818ae4dda23e2bdf5387edbfe74f8a Mon Sep 17 00:00:00 2001 From: Andre Weinand Date: Fri, 13 May 2016 01:22:35 +0200 Subject: [PATCH 158/297] update node-debug --- extensions/node-debug/node-debug.azure.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/node-debug/node-debug.azure.json b/extensions/node-debug/node-debug.azure.json index 2e250bd46fe..01fb5d9123a 100644 --- a/extensions/node-debug/node-debug.azure.json +++ b/extensions/node-debug/node-debug.azure.json @@ -1,6 +1,6 @@ { "account": "monacobuild", "container": "debuggers", - "zip": "a2391c1/node-debug.zip", + "zip": "2a0d6ce/node-debug.zip", "output": "" } From e086d4ec549c84947c9111cd0cbb884daf96c443 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 13 May 2016 09:42:32 +0200 Subject: [PATCH 159/297] some refactorings in reference search, prep for #5893 --- .../browser/referenceSearch.ts | 163 +++++++++--------- .../browser/referenceSearchModel.ts | 37 ++-- .../browser/referenceSearchWidget.ts | 136 +++++++-------- 3 files changed, 153 insertions(+), 183 deletions(-) diff --git a/src/vs/editor/contrib/referenceSearch/browser/referenceSearch.ts b/src/vs/editor/contrib/referenceSearch/browser/referenceSearch.ts index 05ab600f3eb..78755ea96bf 100644 --- a/src/vs/editor/contrib/referenceSearch/browser/referenceSearch.ts +++ b/src/vs/editor/contrib/referenceSearch/browser/referenceSearch.ts @@ -31,7 +31,7 @@ import {ICodeEditor} from 'vs/editor/browser/editorBrowser'; import {EditorBrowserRegistry} from 'vs/editor/browser/editorBrowserExtensions'; import {IPeekViewService, getOuterEditor} from 'vs/editor/contrib/zoneWidget/browser/peekViewWidget'; import {findReferences} from '../common/referenceSearch'; -import {EventType, ReferencesModel} from './referenceSearchModel'; +import {ReferencesModel, OneReference} from './referenceSearchModel'; import {ReferenceWidget, LayoutData} from './referenceSearchWidget'; import {ServicesAccessor} from 'vs/platform/instantiation/common/instantiation'; @@ -39,19 +39,12 @@ export class FindReferencesController implements editorCommon.IEditorContributio public static ID = 'editor.contrib.findReferencesController'; - private _editor:ICodeEditor; - private _widget:ReferenceWidget; - private _requestIdPool: number; - private _callOnClear:Function[]; - private _model:ReferencesModel; - private _modelRevealing:boolean; - - private editorService: IEditorService; - private telemetryService: ITelemetryService; - private messageService: IMessageService; - private instantiationService: IInstantiationService; - private contextService: IWorkspaceContextService; - private peekViewService: IPeekViewService; + private _editor: ICodeEditor; + private _widget: ReferenceWidget; + private _model: ReferencesModel; + private _requestIdPool = 0; + private _callOnClear: Function[] = []; + private _ignoreModelChangeEvent = false; private _startTime: number = -1; private _referenceSearchVisible: IKeybindingContextKey; @@ -62,24 +55,15 @@ export class FindReferencesController implements editorCommon.IEditorContributio public constructor( editor: ICodeEditor, - @IEditorService editorService: IEditorService, - @ITelemetryService telemetryService: ITelemetryService, - @IMessageService messageService: IMessageService, - @IInstantiationService instantiationService: IInstantiationService, @IKeybindingService keybindingService: IKeybindingService, - @IWorkspaceContextService contextService: IWorkspaceContextService, + @IEditorService private _editorService: IEditorService, + @ITelemetryService private _telemetryService: ITelemetryService, + @IMessageService private _messageService: IMessageService, + @IInstantiationService private _instantiationService: IInstantiationService, + @IWorkspaceContextService private _contextService: IWorkspaceContextService, @IStorageService private _storageService: IStorageService, - @optional(IPeekViewService) peekViewService: IPeekViewService + @optional(IPeekViewService) private _peekViewService: IPeekViewService ) { - this._requestIdPool = 0; - this._callOnClear = []; - this.editorService = editorService; - this.telemetryService = telemetryService; - this.messageService = messageService; - this.instantiationService = instantiationService; - this.peekViewService = peekViewService; - this.contextService = contextService; - this._modelRevealing = false; this._editor = editor; this._referenceSearchVisible = keybindingService.createKey(CONTEXT_REFERENCE_SEARCH_VISIBLE, false); } @@ -97,7 +81,7 @@ export class FindReferencesController implements editorCommon.IEditorContributio } public isInPeekView() : boolean { - return this.peekViewService && this.peekViewService.isActive; + return this._peekViewService && this._peekViewService.isActive; } public closeReferenceSearch(): void { @@ -120,13 +104,13 @@ export class FindReferencesController implements editorCommon.IEditorContributio // close the widget on model/mode changes this._callOnClear.push(this._editor.addListener(editorCommon.EventType.ModelModeChanged, () => { this.clear(); })); this._callOnClear.push(this._editor.addListener(editorCommon.EventType.ModelChanged, () => { - if(!this._modelRevealing) { + if(!this._ignoreModelChangeEvent) { this.clear(); } })); const storageKey = 'peekViewLayout'; const data = JSON.parse(this._storageService.get(storageKey, undefined, '{}')); - this._widget = new ReferenceWidget(this._editor, data, this.editorService, this.contextService, this.instantiationService); + this._widget = new ReferenceWidget(this._editor, data, this._editorService, this._contextService, this._instantiationService); this._widget.setTitle(nls.localize('labelLoading', "Loading...")); this._widget.show(range); this._callOnClear.push(this._widget.onDidClose(() => { @@ -137,31 +121,27 @@ export class FindReferencesController implements editorCommon.IEditorContributio this.clear(); }).dispose); - this._callOnClear.push(this._widget.onDidDoubleClick(event => { - - if(!event.reference) { - return; - } - - // open editor - this.editorService.openEditor({ - resource: event.reference, - options: { selection: event.range } - }, event.originalEvent.ctrlKey || event.originalEvent.metaKey).done(null, onUnexpectedError); - - // close zone - if (!(event.originalEvent.ctrlKey || event.originalEvent.metaKey)) { - this.clear(); + this._callOnClear.push(this._widget.onDidSelectReference(event => { + let {element, kind} = event; + switch (kind) { + case 'side': + case 'open': + this._openReference(element, kind === 'side'); + break; + case 'goto': + this._gotoReference(element); + break; } }).dispose); + var requestId = ++this._requestIdPool, editorModel = this._editor.getModel(); - var timer = this.telemetryService.timedPublicLog('findReferences', { + var timer = this._telemetryService.timedPublicLog('findReferences', { mode: editorModel.getMode().getId() }); - referencesPromise.then((references:IReference[]) => { + referencesPromise.then(references => { // still current request? widget still open? if(requestId !== this._requestIdPool || !this._widget) { @@ -177,38 +157,7 @@ export class FindReferencesController implements editorCommon.IEditorContributio } // create result model - this._model = new ReferencesModel(references, this.editorService); - this._model.currentReference = this._model.findReference(editorModel.getAssociatedResource(), range.getStartPosition()); - - var unbind = this._model.addListener(EventType.CurrentReferenceChanged, () => { - - this._modelRevealing = true; - - this.editorService.openEditor({ - resource: this._model.currentReference.resource, - options: { selection: this._model.currentReference.range } - }).done((openedEditor) => { - if(!openedEditor || openedEditor.getControl() !== this._editor) { - // TODO@Alex TODO@Joh - // when opening the current reference we might end up - // in a different editor instance. that means we also have - // a different instance of this reference search controller - // and cannot hold onto the widget (which likely doesn't - // exist). Instead of bailing out we should find the - // 'sister' action and pass our current model on to it. - this.clear(); - return; - } - this._modelRevealing = false; - this._widget.show(this._model.currentReference.range); - this._widget.focus(); - }, (err) => { - this._modelRevealing = false; - onUnexpectedError(err); - }); - }); - - this._callOnClear.push(unbind); + this._model = new ReferencesModel(references, this._editorService); // show widget this._startTime = Date.now(); @@ -219,17 +168,17 @@ export class FindReferencesController implements editorCommon.IEditorContributio timer.stop(); }, (error:any) => { - this.messageService.show(Severity.Error, error); + this._messageService.show(Severity.Error, error); timer.stop(); }); return this._widget; } - private clear():boolean { + private clear(): boolean { if (this._startTime !== -1) { - this.telemetryService.publicLog('zoneWidgetShown', { + this._telemetryService.publicLog('zoneWidgetShown', { mode: 'reference search', elapsedTime: Date.now() - this._startTime }); @@ -237,7 +186,7 @@ export class FindReferencesController implements editorCommon.IEditorContributio } var result = false; - if(this._widget) { + if (this._widget) { this._widget.dispose(); this._widget = null; result = true; @@ -254,8 +203,50 @@ export class FindReferencesController implements editorCommon.IEditorContributio return result; } -} + private _gotoReference(ref: OneReference): void { + this._ignoreModelChangeEvent = true; + const {resource, range} = ref; + this._editorService.openEditor({ + resource, + options: { selection: range } + }).done(openedEditor => { + this._ignoreModelChangeEvent = false; + + if (!openedEditor || openedEditor.getControl() !== this._editor) { + // TODO@Alex TODO@Joh + // when opening the current reference we might end up + // in a different editor instance. that means we also have + // a different instance of this reference search controller + // and cannot hold onto the widget (which likely doesn't + // exist). Instead of bailing out we should find the + // 'sister' action and pass our current model on to it. + this.clear(); + return; + } + + this._widget.show(range); + this._widget.focus(); + + }, (err) => { + this._ignoreModelChangeEvent = false; + onUnexpectedError(err); + }); + } + + private _openReference(ref: OneReference, sideBySide: boolean): void { + const {resource, range} = ref; + this._editorService.openEditor({ + resource, + options: { selection: range } + }, sideBySide); + + // clear stage + if (!sideBySide) { + this.clear(); + } + } +} export class ReferenceAction extends EditorAction { diff --git a/src/vs/editor/contrib/referenceSearch/browser/referenceSearchModel.ts b/src/vs/editor/contrib/referenceSearch/browser/referenceSearchModel.ts index 80d1662df3a..7e54ddba5e9 100644 --- a/src/vs/editor/contrib/referenceSearch/browser/referenceSearchModel.ts +++ b/src/vs/editor/contrib/referenceSearch/browser/referenceSearchModel.ts @@ -6,6 +6,7 @@ import * as collections from 'vs/base/common/collections'; import {EventEmitter} from 'vs/base/common/eventEmitter'; +import Event, {fromEventEmitter} from 'vs/base/common/event'; import {basename, dirname} from 'vs/base/common/paths'; import * as strings from 'vs/base/common/strings'; import URI from 'vs/base/common/uri'; @@ -16,19 +17,16 @@ import {Range} from 'vs/editor/common/core/range'; import {IModel, IPosition, IRange} from 'vs/editor/common/editorCommon'; import {IReference} from 'vs/editor/common/modes'; -export namespace EventType { - export var OnReferenceRangeChanged = 'refrence.rangeChanged'; - export var CurrentReferenceChanged = 'reference.currentChanged'; -} - export class OneReference { private _id: string; - private _range: IRange; - constructor(private _parent: FileReferences, reference: IReference) { + constructor( + private _parent: FileReferences, + private _range: IRange, + private _eventBus: EventEmitter + ) { this._id = generateUuid(); - this._range = reference.range; } public get id(): string { @@ -61,7 +59,7 @@ export class OneReference { public set range(value: IRange) { this._range = value; - this.parent.parent.emit(EventType.OnReferenceRangeChanged, this); + this._eventBus.emit('ref/changed', this); } } @@ -145,16 +143,14 @@ export class FileReferences { } } -export class ReferencesModel extends EventEmitter { +export class ReferencesModel { private _references: FileReferences[]; - private _currentReference: OneReference; + private _eventBus = new EventEmitter(); + + onDidChangeReferenceRange: Event = fromEventEmitter(this._eventBus, 'ref/changed'); constructor(references: IReference[], editorService: IEditorService) { - super([ - EventType.CurrentReferenceChanged, - EventType.OnReferenceRangeChanged - ]); let referencesByFile: { [n: string]: FileReferences } = Object.create(null); let seen: { [n: string]: boolean } = Object.create(null); @@ -169,7 +165,7 @@ export class ReferencesModel extends EventEmitter { let fileReferences = new FileReferences(this, resource, editorService); fileReferences = collections.lookupOrInsert(referencesByFile, fileReferences.id, fileReferences); - fileReferences.children.push(new OneReference(fileReferences, reference)); + fileReferences.children.push(new OneReference(fileReferences, reference.range, this._eventBus)); } }); @@ -181,15 +177,6 @@ export class ReferencesModel extends EventEmitter { return this._references; } - public get currentReference(): OneReference { - return this._currentReference; - } - - public set currentReference(reference: OneReference) { - this._currentReference = reference; - this.emit(EventType.CurrentReferenceChanged, this); - } - public nextReference(reference: OneReference): OneReference { var idx = reference.parent.children.indexOf(reference), diff --git a/src/vs/editor/contrib/referenceSearch/browser/referenceSearchWidget.ts b/src/vs/editor/contrib/referenceSearch/browser/referenceSearchWidget.ts index 5a2ecb7ee09..ca3f188a9c1 100644 --- a/src/vs/editor/contrib/referenceSearch/browser/referenceSearchWidget.ts +++ b/src/vs/editor/contrib/referenceSearch/browser/referenceSearchWidget.ts @@ -13,7 +13,6 @@ import Event, {Emitter} from 'vs/base/common/event'; import {IDisposable, cAll, dispose, Disposables} from 'vs/base/common/lifecycle'; import {Schemas} from 'vs/base/common/network'; import * as strings from 'vs/base/common/strings'; -import URI from 'vs/base/common/uri'; import {TPromise} from 'vs/base/common/winjs.base'; import {$, Builder} from 'vs/base/browser/builder'; import * as dom from 'vs/base/browser/dom'; @@ -37,7 +36,7 @@ import {Model} from 'vs/editor/common/model/model'; import {ICodeEditor, IMouseTarget} from 'vs/editor/browser/editorBrowser'; import {EmbeddedCodeEditorWidget} from 'vs/editor/browser/widget/embeddedCodeEditorWidget'; import {PeekViewWidget, IPeekViewService} from 'vs/editor/contrib/zoneWidget/browser/peekViewWidget'; -import {EventType, FileReferences, OneReference, ReferencesModel} from './referenceSearchModel'; +import {FileReferences, OneReference, ReferencesModel} from './referenceSearchModel'; class DecorationsManager implements IDisposable { @@ -433,6 +432,11 @@ export interface LayoutData { heightInLines: number; } +export interface SelectionEvent { + kind: 'goto' | 'show' | 'side' | 'open'; + element: OneReference; +} + /** * ZoneWidget that is shown inside the editor */ @@ -440,10 +444,11 @@ export class ReferenceWidget extends PeekViewWidget { public static INNER_EDITOR_CONTEXT_KEY = 'inReferenceSearchEditor'; - private _decorationsManager: DecorationsManager; private _model: ReferencesModel; - private _callOnModel: IDisposable[] = []; - private _onDidDoubleClick = new Emitter<{ reference: URI, range: Range, originalEvent: MouseEvent }>(); + private _decorationsManager: DecorationsManager; + + private _disposeOnNewModel: IDisposable[] = []; + private _onDidSelectReference = new Emitter(); private _tree: Tree; private _treeContainer: Builder; @@ -472,23 +477,26 @@ export class ReferenceWidget extends PeekViewWidget { super.dispose(); } - get onDidDoubleClick():Event<{ reference: URI, range: Range, originalEvent: MouseEvent }> { - return this._onDidDoubleClick.event; + get onDidSelectReference(): Event { + return this._onDidSelectReference.event; } show(where: editorCommon.IRange) { + this.editor.revealRangeInCenterIfOutsideViewport(where); super.show(where, this.layoutData.heightInLines || 18); } - protected _onTitleClick(e: MouseEvent): void { - if (!this._preview || !this._preview.getModel()) { - return; - } - var model = this._preview.getModel(), - lineNumber = this._preview.getPosition().lineNumber, - titleRange = new Range(lineNumber, 1, lineNumber, model.getLineMaxColumn(lineNumber)); + focus(): void { + this._tree.DOMFocus(); + } - this._onDidDoubleClick.fire({ reference: this._getFocusedReference(), range: titleRange, originalEvent: e }); + protected _onTitleClick(e: MouseEvent): void { + if (this._preview && this._preview.getModel()) { + this._onDidSelectReference.fire({ + element: this._getFocusedReference(), + kind: e.ctrlKey || e.metaKey ? 'side' : 'open' + }); + } } protected _fillBody(containerElement: HTMLElement): void { @@ -574,65 +582,56 @@ export class ReferenceWidget extends PeekViewWidget { this._preview.layout(); } + public showMessage(message: string): void { + this.setTitle(''); + this._messageContainer.innerHtml(message).show(); + } + public setModel(newModel: ReferencesModel): void { // clean up - this._callOnModel = dispose(this._callOnModel); + this._disposeOnNewModel = dispose(this._disposeOnNewModel); this._model = newModel; if (this._model) { this._onNewModel(); } } - public showMessage(message: string): void { - this.setTitle(''); - this._messageContainer.innerHtml(message).show(); - } - private _onNewModel(): void { this._messageContainer.hide(); this._decorationsManager = new DecorationsManager(this._preview, this._model); - this._callOnModel.push(this._decorationsManager); + this._disposeOnNewModel.push(this._decorationsManager); // listen on model changes - this._callOnModel.push(this._model.addListener2(EventType.OnReferenceRangeChanged, (reference: OneReference) => { - this._tree.refresh(reference); - })); + this._disposeOnNewModel.push(this._model.onDidChangeReferenceRange(reference => this._tree.refresh(reference))); // listen on selection and focus - this._callOnModel.push(this._tree.addListener2(Controller.Events.FOCUSED, (element) => { + this._disposeOnNewModel.push(this._tree.addListener2(Controller.Events.FOCUSED, (element) => { if (element instanceof OneReference) { - this._showReferencePreview(element); + this._onDidSelectReference.fire({ element, kind: 'show' }); + this._revealReference(element); } })); - this._callOnModel.push(this._tree.addListener2(Controller.Events.SELECTED, (element: any) => { + this._disposeOnNewModel.push(this._tree.addListener2(Controller.Events.SELECTED, (element: any) => { if (element instanceof OneReference) { - this._showReferencePreview(element); - this._model.currentReference = element; + this._onDidSelectReference.fire({ element, kind: 'goto' }); + this._revealReference(element); } })); - this._callOnModel.push(this._tree.addListener2(Controller.Events.OPEN_TO_SIDE, (element: any) => { + this._disposeOnNewModel.push(this._tree.addListener2(Controller.Events.OPEN_TO_SIDE, (element: any) => { if (element instanceof OneReference) { - this._editorService.openEditor({ - resource: (element).resource, - options: { - selection: element.range - } - }, true); + this._onDidSelectReference.fire({ element, kind: 'side' }); } })); - var input = this._model.children.length === 1 ? this._model.children[0] : this._model; - - this._tree.setInput(input).then(() => { - this._tree.setSelection([this._model.currentReference]); - }).done(null, onUnexpectedError); - // listen on editor - this._callOnModel.push(this._preview.addListener2(editorCommon.EventType.MouseDown, (e: { event: MouseEvent; target: IMouseTarget; }) => { + this._disposeOnNewModel.push(this._preview.addListener2(editorCommon.EventType.MouseDown, (e: { event: MouseEvent; target: IMouseTarget; }) => { if (e.event.detail === 2) { - this._onDidDoubleClick.fire({ reference: this._getFocusedReference(), range: e.target.range, originalEvent: e.event }); + this._onDidSelectReference.fire({ + element: this._getFocusedReference(), + kind: (e.event.ctrlKey || e.event.metaKey) ? 'side' : 'open' + }); } })); @@ -644,28 +643,31 @@ export class ReferenceWidget extends PeekViewWidget { this._tree.layout(); this.focus(); - // preview the current reference - this._showReferencePreview(this._model.nextReference(this._model.currentReference)); + // pick input and a reference to begin with + const input = this._model.children.length === 1 ? this._model.children[0] : this._model; + const selection = this._model.children[0].children[0]; + this._tree.setInput(input).then(() => this._revealReference(selection)); } - private _getFocusedReference(): URI { - var element = this._tree.getFocus(); + private _getFocusedReference(): OneReference { + const element = this._tree.getFocus(); if (element instanceof OneReference) { - return (element).resource; + return element; } else if (element instanceof FileReferences) { - var referenceFile = (element); - if (referenceFile.children.length > 0) { - return referenceFile.children[0].resource; + if (element.children.length > 0) { + return element.children[0]; } } - return null; } - public focus(): void { - this._tree.DOMFocus(); - } + private _revealReference(reference: OneReference): void { - private _showReferencePreview(reference: OneReference): void { + // Update widget header + if (reference.resource.scheme !== Schemas.inMemory) { + this.setTitle(reference.name, getPathLabel(reference.directory, this._contextService)); + } else { + this.setTitle(nls.localize('peekView.alternateTitle', "References")); + } // show in editor this._editorService.resolveEditorModel({ resource: reference.resource }).done((model) => { @@ -679,22 +681,12 @@ export class ReferenceWidget extends PeekViewWidget { this._preview.setModel(this._previewNotAvailableMessage); } - // Update widget header - if (reference.resource.scheme !== Schemas.inMemory) { - this.setTitle(reference.name, getPathLabel(reference.directory, this._contextService)); - } else { - this.setTitle(nls.localize('peekView.alternateTitle', "References")); - } - }, onUnexpectedError); // show in tree - this._tree.reveal(reference) - .then(() => { - this._tree.setSelection([reference]); - this._tree.setFocus(reference); - }) - .done(null, onUnexpectedError); + this._tree.reveal(reference).then(() => { + this._tree.setSelection([reference]); + this._tree.setFocus(reference); + }); } - } From 0d827d8e350fa761ba7e1491f8d5c8fe6f68a481 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 13 May 2016 12:34:41 +0200 Subject: [PATCH 160/297] for multiple definitions open peek at the first location and close it when jumping to another, fixes #5893 --- .../browser/goToDeclaration.ts | 286 +++++++----------- .../browser/referenceSearch.ts | 56 ++-- .../browser/referenceSearchWidget.ts | 24 +- 3 files changed, 153 insertions(+), 213 deletions(-) diff --git a/src/vs/editor/contrib/goToDeclaration/browser/goToDeclaration.ts b/src/vs/editor/contrib/goToDeclaration/browser/goToDeclaration.ts index e5a2533c3c1..f00d0f539d5 100644 --- a/src/vs/editor/contrib/goToDeclaration/browser/goToDeclaration.ts +++ b/src/vs/editor/contrib/goToDeclaration/browser/goToDeclaration.ts @@ -7,7 +7,6 @@ import 'vs/css!./goToDeclaration'; import * as nls from 'vs/nls'; -import {coalesce} from 'vs/base/common/arrays'; import {Throttler} from 'vs/base/common/async'; import {onUnexpectedError} from 'vs/base/common/errors'; import {ListenerUnbind} from 'vs/base/common/eventEmitter'; @@ -16,7 +15,6 @@ import {KeyCode, KeyMod} from 'vs/base/common/keyCodes'; import * as platform from 'vs/base/common/platform'; import Severity from 'vs/base/common/severity'; import * as strings from 'vs/base/common/strings'; -import URI from 'vs/base/common/uri'; import {TPromise} from 'vs/base/common/winjs.base'; import * as browser from 'vs/base/browser/browser'; import {IKeyboardEvent} from 'vs/base/browser/keyboardEvent'; @@ -32,132 +30,30 @@ import {tokenizeToHtmlContent} from 'vs/editor/common/modes/textToHtmlTokenizer' import {ICodeEditor, IEditorMouseEvent, IMouseTarget} from 'vs/editor/browser/editorBrowser'; import {EditorBrowserRegistry} from 'vs/editor/browser/editorBrowserExtensions'; import {getDeclarationsAtPosition} from 'vs/editor/contrib/goToDeclaration/common/goToDeclaration'; -import {FindReferencesController} from 'vs/editor/contrib/referenceSearch/browser/referenceSearch'; +import {ReferencesController} from 'vs/editor/contrib/referenceSearch/browser/referenceSearch'; -const DEFAULT_BEHAVIOR = Behaviour.WidgetFocus | Behaviour.ShowInContextMenu | Behaviour.UpdateOnCursorPositionChange; +export class DefitiontionActionConfig { -function metaTitle(references: IReference[]): string { - if (references.length > 1) { - return nls.localize('meta.title', " – {0} definitions", references.length); + constructor( + public condition = Behaviour.WidgetFocus | Behaviour.ShowInContextMenu | Behaviour.UpdateOnCursorPositionChange, + public openToSide = false, + public openInPeek = false, + public filterCurrent = true + ) { + // } } -export abstract class GoToTypeAction extends EditorAction { +export class DefinitionAction extends EditorAction { constructor( descriptor: editorCommon.IEditorActionDescriptorData, editor: editorCommon.ICommonCodeEditor, private _messageService: IMessageService, private _editorService: IEditorService, - condition = DEFAULT_BEHAVIOR + private _configuration: DefitiontionActionConfig ) { - super(descriptor, editor, condition); - } - - public run(): TPromise { - let model = this.editor.getModel(); - let position = this.editor.getPosition(); - let promise = this._resolve(model.getAssociatedResource(), { lineNumber: position.lineNumber, column: position.column }); - - return promise.then(references => { - - // remove falsy entries - references = coalesce(references); - if (!references || references.length === 0) { - return; - } - - // only use the start position - references = references.map(reference => { - return { - resource: reference.resource, - range: Range.collapseToStart(reference.range) - }; - }); - - // open and reveal - if (references.length === 1 && !this._showSingleReferenceInPeek()) { - return this._editorService.openEditor({ - resource: references[0].resource, - options: { selection: references[0].range } - }, this.openToTheSide); - - } else { - let controller = FindReferencesController.getController(this.editor); - return controller.processRequest(this.editor.getSelection(), TPromise.as(references), metaTitle); - } - - }, (err) => { - // report an error - this._messageService.show(Severity.Error, err); - return false; - }); - } - - protected get openToTheSide(): boolean { - return false; - } - - protected abstract _resolve(resource: URI, position: editorCommon.IPosition): TPromise; - - protected _showSingleReferenceInPeek() { - return false; - } -} - -export class GoToTypeDeclarationActions extends GoToTypeAction { - - public static ID = 'editor.action.goToTypeDeclaration'; - - constructor( - descriptor: editorCommon.IEditorActionDescriptorData, - editor: editorCommon.ICommonCodeEditor, - @IMessageService messageService: IMessageService, - @IEditorService editorService: IEditorService - ) { - super(descriptor, editor, messageService, editorService); - } - - public getGroupId(): string { - return '1_goto/3_visitTypeDefinition'; - } - - public isSupported(): boolean { - return !!this.editor.getModel().getMode().typeDeclarationSupport && super.isSupported(); - } - - public getEnablementState(): boolean { - if (!super.getEnablementState()) { - return false; - } - - let model = this.editor.getModel(), - position = this.editor.getSelection().getStartPosition(); - - return model.getMode().typeDeclarationSupport.canFindTypeDeclaration( - model.getLineContext(position.lineNumber), - position.column - 1 - ); - } - - protected _resolve(resource: URI, position: editorCommon.IPosition): TPromise { - let typeDeclarationSupport = this.editor.getModel().getMode().typeDeclarationSupport; - if (typeDeclarationSupport) { - return typeDeclarationSupport.findTypeDeclaration(resource, position).then(value => [value]); - } - } -} - -export abstract class BaseGoToDeclarationAction extends GoToTypeAction { - - constructor( - descriptor: editorCommon.IEditorActionDescriptorData, - editor: editorCommon.ICommonCodeEditor, - messageService: IMessageService, - editorService: IEditorService, - condition: Behaviour - ) { - super(descriptor, editor, messageService, editorService, condition); + super(descriptor, editor, _configuration.condition); } public getGroupId(): string { @@ -173,9 +69,8 @@ export abstract class BaseGoToDeclarationAction extends GoToTypeAction { return false; } - let model = this.editor.getModel(), - position = this.editor.getSelection().getStartPosition(); - + const model = this.editor.getModel(); + const position = this.editor.getSelection().getStartPosition(); return DeclarationRegistry.all(model).some(provider => { return provider.canFindDeclaration( model.getLineContext(position.lineNumber), @@ -183,13 +78,86 @@ export abstract class BaseGoToDeclarationAction extends GoToTypeAction { }); } + public run(): TPromise { - protected _resolve(resource: URI, position: editorCommon.IPosition): TPromise { - return getDeclarationsAtPosition(this.editor.getModel(), this.editor.getPosition()); + let model = this.editor.getModel(); + let pos = this.editor.getPosition(); + + return getDeclarationsAtPosition(model, pos).then(references => { + + if (!references) { + return; + } + + // * remove falsy references + // * remove reference at the current pos + // * collapse ranges to start pos + let result: IReference[] = []; + for (let i = 0; i < references.length; i++) { + let reference = references[i]; + if (!reference) { + continue; + } + let {resource, range} = reference; + if (!this._configuration.filterCurrent + || resource.toString() !== model.getAssociatedResource().toString() + || !Range.containsPosition(range, pos)) { + + result.push({ + resource, + range: Range.collapseToStart(range) + }); + } + } + + if (result.length === 0) { + return; + } + + return this._onResult(result); + + }, (err) => { + // report an error + this._messageService.show(Severity.Error, err); + return false; + }); + } + + private _onResult(references: IReference[]) { + if (this._configuration.openInPeek) { + this._openInPeek(this.editor, references); + } else { + let [first] = references; + this._openReference(first, this._configuration.openToSide).then(editor => { + if (references.length > 1) { + this._openInPeek(editor, references); + } + }); + } + } + + private _openReference(reference: IReference, sideBySide: boolean): TPromise{ + let {resource, range} = reference; + return this._editorService.openEditor({ resource, options: { selection: range } }, sideBySide).then(editor => { + return editor.getControl(); + }); + } + + private _openInPeek(target: editorCommon.ICommonCodeEditor, references: IReference[]) { + let controller = ReferencesController.getController(target); + controller.processRequest(target.getSelection(), TPromise.as(references), { + getMetaTitle: (references) => { + return references.length > 1 && nls.localize('meta.title', " – {0} definitions", references.length); + }, + onGoto: (reference) => { + controller.closeReferenceSearch(); + return this._openReference(reference, false); + } + }); } } -export class GoToDeclarationAction extends BaseGoToDeclarationAction { +export class GoToDefinitionAction extends DefinitionAction { public static ID = 'editor.action.goToDeclaration'; @@ -199,11 +167,12 @@ export class GoToDeclarationAction extends BaseGoToDeclarationAction { @IMessageService messageService: IMessageService, @IEditorService editorService: IEditorService ) { - super(descriptor, editor, messageService, editorService, DEFAULT_BEHAVIOR); + super(descriptor, editor, messageService, editorService, new DefitiontionActionConfig()); } + } -export class OpenDeclarationToTheSideAction extends BaseGoToDeclarationAction { +export class OpenDefinitionToSideAction extends DefinitionAction { public static ID = 'editor.action.openDeclarationToTheSide'; @@ -213,15 +182,11 @@ export class OpenDeclarationToTheSideAction extends BaseGoToDeclarationAction { @IMessageService messageService: IMessageService, @IEditorService editorService: IEditorService ) { - super(descriptor, editor, messageService, editorService, Behaviour.WidgetFocus | Behaviour.UpdateOnCursorPositionChange); - } - - protected get openToTheSide(): boolean { - return true; + super(descriptor, editor, messageService, editorService, new DefitiontionActionConfig(Behaviour.WidgetFocus | Behaviour.UpdateOnCursorPositionChange, true)); } } -export class PreviewDeclarationAction extends BaseGoToDeclarationAction { +export class PeekDefinitionAction extends DefinitionAction { public static ID = 'editor.action.previewDeclaration'; @@ -231,11 +196,7 @@ export class PreviewDeclarationAction extends BaseGoToDeclarationAction { @IMessageService messageService: IMessageService, @IEditorService editorService: IEditorService ) { - super(descriptor, editor, messageService, editorService, DEFAULT_BEHAVIOR); - } - - protected _showSingleReferenceInPeek() { - return true; + super(descriptor, editor, messageService, editorService, new DefitiontionActionConfig(void 0, void 0, true, false)); } } @@ -251,7 +212,6 @@ class GotoDefinitionWithMouseEditorContribution implements editorCommon.IEditorC private editor: ICodeEditor; private toUnhook: ListenerUnbind[]; - private hasRequiredServices: boolean; private decorations: string[]; private currentWordUnderMouse: editorCommon.IWordAtPosition; private throttler: Throttler; @@ -262,8 +222,6 @@ class GotoDefinitionWithMouseEditorContribution implements editorCommon.IEditorC editor: ICodeEditor, @IEditorService private editorService: IEditorService ) { - this.hasRequiredServices = !!this.editorService; - this.toUnhook = []; this.decorations = []; this.editor = editor; @@ -472,8 +430,7 @@ class GotoDefinitionWithMouseEditorContribution implements editorCommon.IEditorC } private isEnabled(mouseEvent: IEditorMouseEvent, withKey?: IKeyboardEvent): boolean { - return this.hasRequiredServices && - this.editor.getModel() && + return this.editor.getModel() && (browser.isIE11orEarlier || mouseEvent.event.detail <= 1) && // IE does not support event.detail properly mouseEvent.target.type === editorCommon.MouseTargetType.CONTENT_TEXT && (mouseEvent.event[GotoDefinitionWithMouseEditorContribution.TRIGGER_MODIFIER] || (withKey && withKey.keyCode === GotoDefinitionWithMouseEditorContribution.TRIGGER_KEY_VALUE)) && @@ -490,44 +447,14 @@ class GotoDefinitionWithMouseEditorContribution implements editorCommon.IEditorC } private gotoDefinition(target: IMouseTarget, sideBySide: boolean): TPromise { - let state = this.editor.captureState(editorCommon.CodeEditorStateFlag.Position, editorCommon.CodeEditorStateFlag.Value, editorCommon.CodeEditorStateFlag.Selection, editorCommon.CodeEditorStateFlag.Scroll); - return this.findDefinition(target).then((results: IReference[]) => { - if (!results || !results.length || !state.validate(this.editor)) { - return; - } + const targetAction = sideBySide + ? OpenDefinitionToSideAction.ID + : GoToDefinitionAction.ID; - let position = target.position; - let word = this.editor.getModel().getWordAtPosition(position); - - // Find valid target (and not the same position as the current hovered word) - let validResults = results - .filter(result => result.range && !(word && result.range.startColumn === word.startColumn && result.range.startLineNumber === target.position.lineNumber)) - .map((result) => { - return { - resource: result.resource, - range: Range.collapseToStart(result.range) - }; - }); - - if (!validResults.length) { - return; - } - - // Muli result: Show in references UI - if (validResults.length > 1) { - let controller = FindReferencesController.getController(this.editor); - return controller.processRequest(this.editor.getSelection(), TPromise.as(validResults), metaTitle); - } - - // Single result: Open - return this.editorService.openEditor({ - resource: validResults[0].resource, - options: { - selection: validResults[0].range - } - }, sideBySide); - }); + // just run the corresponding action + this.editor.setPosition(target.position); + return this.editor.getAction(targetAction).run(); } public getId(): string { @@ -542,7 +469,7 @@ class GotoDefinitionWithMouseEditorContribution implements editorCommon.IEditorC } // register actions -CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(PreviewDeclarationAction, PreviewDeclarationAction.ID, nls.localize('actions.previewDecl.label', "Peek Definition"), { +CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(PeekDefinitionAction, PeekDefinitionAction.ID, nls.localize('actions.previewDecl.label', "Peek Definition"), { context: ContextKey.EditorTextFocus, primary: KeyMod.Alt | KeyCode.F12, linux: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.F10 }, @@ -555,15 +482,14 @@ if (platform.isWeb) { goToDeclarationKb = KeyCode.F12; } -CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(GoToDeclarationAction, GoToDeclarationAction.ID, nls.localize('actions.goToDecl.label', "Go to Definition"), { +CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(GoToDefinitionAction, GoToDefinitionAction.ID, nls.localize('actions.goToDecl.label', "Go to Definition"), { context: ContextKey.EditorTextFocus, primary: goToDeclarationKb }, 'Go to Definition')); -CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(OpenDeclarationToTheSideAction, OpenDeclarationToTheSideAction.ID, nls.localize('actions.goToDeclToSide.label', "Open Definition to the Side"), { +CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(OpenDefinitionToSideAction, OpenDefinitionToSideAction.ID, nls.localize('actions.goToDeclToSide.label', "Open Definition to the Side"), { context: ContextKey.EditorTextFocus, primary: KeyMod.chord(KeyMod.CtrlCmd | KeyCode.KEY_K, goToDeclarationKb) }, 'Open Definition to the Side')); -CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(GoToTypeDeclarationActions, GoToTypeDeclarationActions.ID, nls.localize('actions.gotoTypeDecl.label', "Go to Type Definition"), void 0, 'Go to Type Definition')); EditorBrowserRegistry.registerEditorContribution(GotoDefinitionWithMouseEditorContribution); diff --git a/src/vs/editor/contrib/referenceSearch/browser/referenceSearch.ts b/src/vs/editor/contrib/referenceSearch/browser/referenceSearch.ts index 78755ea96bf..ad0c6923141 100644 --- a/src/vs/editor/contrib/referenceSearch/browser/referenceSearch.ts +++ b/src/vs/editor/contrib/referenceSearch/browser/referenceSearch.ts @@ -35,9 +35,21 @@ import {ReferencesModel, OneReference} from './referenceSearchModel'; import {ReferenceWidget, LayoutData} from './referenceSearchWidget'; import {ServicesAccessor} from 'vs/platform/instantiation/common/instantiation'; -export class FindReferencesController implements editorCommon.IEditorContribution { +export interface RequestOptions { + getMetaTitle(references: IReference[]): string; + onGoto(reference: IReference): TPromise; +} - public static ID = 'editor.contrib.findReferencesController'; +const defaultReferenceSearchOptions: RequestOptions = { + getMetaTitle(references: IReference[]) { + return references.length > 1 && nls.localize('meta.titleReference', " – {0} references", references.length); + }, + onGoto: undefined +}; + +export class ReferencesController implements editorCommon.IEditorContribution { + + public static ID = 'editor.contrib.referencesController'; private _editor: ICodeEditor; private _widget: ReferenceWidget; @@ -49,8 +61,8 @@ export class FindReferencesController implements editorCommon.IEditorContributio private _startTime: number = -1; private _referenceSearchVisible: IKeybindingContextKey; - static getController(editor:editorCommon.ICommonCodeEditor): FindReferencesController { - return editor.getContribution(FindReferencesController.ID); + static getController(editor:editorCommon.ICommonCodeEditor): ReferencesController { + return editor.getContribution(ReferencesController.ID); } public constructor( @@ -69,7 +81,7 @@ export class FindReferencesController implements editorCommon.IEditorContributio } public getId(): string { - return FindReferencesController.ID; + return ReferencesController.ID; } public dispose(): void { @@ -88,7 +100,7 @@ export class FindReferencesController implements editorCommon.IEditorContributio this.clear(); } - public processRequest(range: editorCommon.IEditorRange, referencesPromise: TPromise, metaTitleFn:(references:IReference[])=>string) : ReferenceWidget { + public processRequest(range: editorCommon.IEditorRange, referencesPromise: TPromise, options: RequestOptions) : void { var widgetPosition = !this._widget ? null : this._widget.position; // clean up from previous invocation @@ -129,7 +141,11 @@ export class FindReferencesController implements editorCommon.IEditorContributio this._openReference(element, kind === 'side'); break; case 'goto': - this._gotoReference(element); + if (options.onGoto) { + options.onGoto(element); + } else { + this._gotoReference(element); + } break; } }).dispose); @@ -162,7 +178,7 @@ export class FindReferencesController implements editorCommon.IEditorContributio // show widget this._startTime = Date.now(); if (this._widget) { - this._widget.setMetaTitle(metaTitleFn(references)); + this._widget.setMetaTitle(options.getMetaTitle(references)); this._widget.setModel(this._model); } timer.stop(); @@ -171,8 +187,6 @@ export class FindReferencesController implements editorCommon.IEditorContributio this._messageService.show(Severity.Error, error); timer.stop(); }); - - return this._widget; } private clear(): boolean { @@ -299,14 +313,8 @@ export class ReferenceAction extends EditorAction { let range = this.editor.getSelection(); let model = this.editor.getModel(); let request = findReferences(model, range.getStartPosition()); - let controller = FindReferencesController.getController(this.editor); - return TPromise.as(controller.processRequest(range, request, metaTitle)).then(() => true); - } -} - -function metaTitle(references: IReference[]): string { - if (references.length > 1) { - return nls.localize('meta.titleReference', " – {0} references", references.length); + let controller = ReferencesController.getController(this.editor); + return TPromise.as(controller.processRequest(range, request, defaultReferenceSearchOptions)).then(() => true); } } @@ -327,9 +335,9 @@ let findReferencesCommand: ICommandHandler = (accessor:ServicesAccessor, resourc } let request = findReferences(control.getModel(), position); - let controller = FindReferencesController.getController(control); + let controller = ReferencesController.getController(control); let range = new Range(position.lineNumber, position.column, position.lineNumber, position.column); - return TPromise.as(controller.processRequest(range, request, metaTitle)); + return TPromise.as(controller.processRequest(range, request, defaultReferenceSearchOptions)); }); }; @@ -345,16 +353,16 @@ let showReferencesCommand: ICommandHandler = (accessor:ServicesAccessor, resourc return; } - let controller = FindReferencesController.getController(control); + let controller = ReferencesController.getController(control); let range = Position.asEmptyRange(position); - return TPromise.as(controller.processRequest(Range.lift(range), TPromise.as(references), metaTitle)).then(() => true); + return TPromise.as(controller.processRequest(Range.lift(range), TPromise.as(references), defaultReferenceSearchOptions)).then(() => true); }); }; var CONTEXT_REFERENCE_SEARCH_VISIBLE = 'referenceSearchVisible'; // register action -EditorBrowserRegistry.registerEditorContribution(FindReferencesController); +EditorBrowserRegistry.registerEditorContribution(ReferencesController); CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(ReferenceAction, ReferenceAction.ID, nls.localize('references.action.name', "Show References"), { context: ContextKey.EditorTextFocus, primary: KeyMod.Shift | KeyCode.F12 @@ -385,7 +393,7 @@ KeybindingsRegistry.registerCommandDesc({ function closeActiveReferenceSearch(accessor, args) { var outerEditor = getOuterEditor(accessor, args); if (outerEditor) { - var controller = FindReferencesController.getController(outerEditor); + var controller = ReferencesController.getController(outerEditor); controller.closeReferenceSearch(); } } diff --git a/src/vs/editor/contrib/referenceSearch/browser/referenceSearchWidget.ts b/src/vs/editor/contrib/referenceSearch/browser/referenceSearchWidget.ts index ca3f188a9c1..8445015f46d 100644 --- a/src/vs/editor/contrib/referenceSearch/browser/referenceSearchWidget.ts +++ b/src/vs/editor/contrib/referenceSearch/browser/referenceSearchWidget.ts @@ -609,14 +609,14 @@ export class ReferenceWidget extends PeekViewWidget { // listen on selection and focus this._disposeOnNewModel.push(this._tree.addListener2(Controller.Events.FOCUSED, (element) => { if (element instanceof OneReference) { - this._onDidSelectReference.fire({ element, kind: 'show' }); this._revealReference(element); + this._onDidSelectReference.fire({ element, kind: 'show' }); } })); this._disposeOnNewModel.push(this._tree.addListener2(Controller.Events.SELECTED, (element: any) => { if (element instanceof OneReference) { - this._onDidSelectReference.fire({ element, kind: 'goto' }); this._revealReference(element); + this._onDidSelectReference.fire({ element, kind: 'goto' }); } })); this._disposeOnNewModel.push(this._tree.addListener2(Controller.Events.OPEN_TO_SIDE, (element: any) => { @@ -669,9 +669,17 @@ export class ReferenceWidget extends PeekViewWidget { this.setTitle(nls.localize('peekView.alternateTitle', "References")); } - // show in editor - this._editorService.resolveEditorModel({ resource: reference.resource }).done((model) => { + TPromise.join([ + this._editorService.resolveEditorModel({ resource: reference.resource }), + this._tree.reveal(reference) + ]).done(values => { + if (!this._model) { + // disposed + return; + } + // show in editor + let [model] = values; if (model) { this._preview.setModel(model.textEditorModel); var sel = Range.lift(reference.range).collapseToStart(); @@ -681,12 +689,10 @@ export class ReferenceWidget extends PeekViewWidget { this._preview.setModel(this._previewNotAvailableMessage); } - }, onUnexpectedError); - - // show in tree - this._tree.reveal(reference).then(() => { + // show in tree this._tree.setSelection([reference]); this._tree.setFocus(reference); - }); + + }, onUnexpectedError); } } From de77d32034696d152467343bcb8a946bbc91676b Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 13 May 2016 12:34:56 +0200 Subject: [PATCH 161/297] remove unused type declaration support --- src/vs/editor/common/modes.ts | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/vs/editor/common/modes.ts b/src/vs/editor/common/modes.ts index 96e2d02ba00..fe236fd01a4 100644 --- a/src/vs/editor/common/modes.ts +++ b/src/vs/editor/common/modes.ts @@ -196,11 +196,6 @@ export interface IMode { */ declarationSupport?: IDeclarationSupport; - /** - * Optional adapter to support revealing the type declaration of a symbol. - */ - typeDeclarationSupport?: ITypeDeclarationSupport; - /** * Optional adapter to support finding references to a symbol. */ @@ -476,11 +471,6 @@ export interface IDeclarationSupport { findDeclaration(resource:URI, position:editorCommon.IPosition):TPromise; } -export interface ITypeDeclarationSupport { - canFindTypeDeclaration(context:ILineContext, offset:number):boolean; - findTypeDeclaration(resource:URI, position:editorCommon.IPosition):TPromise; -} - /** * Interface used to compute an outline */ From 8cd47bb55ef19b68c3ab1b26d63f89f8b01d00a0 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 13 May 2016 15:09:42 +0200 Subject: [PATCH 162/297] Fixes #6281: Do not truncate line number, column in position --- .../vscode-api-tests/src/editor.test.ts | 25 ++++++++++++++++++- src/vs/editor/common/core/position.ts | 4 +-- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/extensions/vscode-api-tests/src/editor.test.ts b/extensions/vscode-api-tests/src/editor.test.ts index e3bb24f42c2..13388234f78 100644 --- a/extensions/vscode-api-tests/src/editor.test.ts +++ b/extensions/vscode-api-tests/src/editor.test.ts @@ -8,7 +8,7 @@ import * as assert from 'assert'; import * as fs from 'fs'; import * as os from 'os'; -import {workspace, window, Position} from 'vscode'; +import {workspace, window, Position, Range} from 'vscode'; import {createRandomFile, deleteFile, cleanUp} from './utils'; import {join} from 'path'; @@ -38,4 +38,27 @@ suite("editor tests", () => { }); }); }); + + test('issue #6281: Edits fail to validate ranges correctly before applying', () => { + return createRandomFile('Hello world!').then(file => { + return workspace.openTextDocument(file).then(doc => { + return window.showTextDocument(doc).then((editor) => { + return editor.edit((builder) => { + builder.replace(new Range(0, 0, Number.MAX_VALUE, Number.MAX_VALUE), 'new'); + }).then(applied => { + assert.ok(applied); + assert.equal(doc.getText(), 'new'); + assert.ok(doc.isDirty); + + return doc.save().then(saved => { + assert.ok(saved); + assert.ok(!doc.isDirty); + + return deleteFile(file); + }); + }); + }); + }); + }); + }); }); \ No newline at end of file diff --git a/src/vs/editor/common/core/position.ts b/src/vs/editor/common/core/position.ts index 831442b1fcb..8094514361d 100644 --- a/src/vs/editor/common/core/position.ts +++ b/src/vs/editor/common/core/position.ts @@ -12,8 +12,8 @@ export class Position implements IEditorPosition { public column: number; constructor(lineNumber: number, column: number) { - this.lineNumber = lineNumber|0; - this.column = column|0; + this.lineNumber = lineNumber; + this.column = column; } public equals(other:IPosition): boolean { From 6e2c5735961749b0bddd5b219e4f1610dc1f95b7 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 13 May 2016 15:27:43 +0200 Subject: [PATCH 163/297] fix typo, #5893 --- .../contrib/goToDeclaration/browser/goToDeclaration.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/vs/editor/contrib/goToDeclaration/browser/goToDeclaration.ts b/src/vs/editor/contrib/goToDeclaration/browser/goToDeclaration.ts index f00d0f539d5..d17b61e1809 100644 --- a/src/vs/editor/contrib/goToDeclaration/browser/goToDeclaration.ts +++ b/src/vs/editor/contrib/goToDeclaration/browser/goToDeclaration.ts @@ -32,7 +32,7 @@ import {EditorBrowserRegistry} from 'vs/editor/browser/editorBrowserExtensions'; import {getDeclarationsAtPosition} from 'vs/editor/contrib/goToDeclaration/common/goToDeclaration'; import {ReferencesController} from 'vs/editor/contrib/referenceSearch/browser/referenceSearch'; -export class DefitiontionActionConfig { +export class DefinitionActionConfig { constructor( public condition = Behaviour.WidgetFocus | Behaviour.ShowInContextMenu | Behaviour.UpdateOnCursorPositionChange, @@ -51,7 +51,7 @@ export class DefinitionAction extends EditorAction { editor: editorCommon.ICommonCodeEditor, private _messageService: IMessageService, private _editorService: IEditorService, - private _configuration: DefitiontionActionConfig + private _configuration: DefinitionActionConfig ) { super(descriptor, editor, _configuration.condition); } @@ -167,7 +167,7 @@ export class GoToDefinitionAction extends DefinitionAction { @IMessageService messageService: IMessageService, @IEditorService editorService: IEditorService ) { - super(descriptor, editor, messageService, editorService, new DefitiontionActionConfig()); + super(descriptor, editor, messageService, editorService, new DefinitionActionConfig()); } } @@ -182,7 +182,7 @@ export class OpenDefinitionToSideAction extends DefinitionAction { @IMessageService messageService: IMessageService, @IEditorService editorService: IEditorService ) { - super(descriptor, editor, messageService, editorService, new DefitiontionActionConfig(Behaviour.WidgetFocus | Behaviour.UpdateOnCursorPositionChange, true)); + super(descriptor, editor, messageService, editorService, new DefinitionActionConfig(Behaviour.WidgetFocus | Behaviour.UpdateOnCursorPositionChange, true)); } } @@ -196,7 +196,7 @@ export class PeekDefinitionAction extends DefinitionAction { @IMessageService messageService: IMessageService, @IEditorService editorService: IEditorService ) { - super(descriptor, editor, messageService, editorService, new DefitiontionActionConfig(void 0, void 0, true, false)); + super(descriptor, editor, messageService, editorService, new DefinitionActionConfig(void 0, void 0, true, false)); } } From d4d14888ae62cb22d020fc620764c16dc4297a74 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 13 May 2016 16:25:13 +0200 Subject: [PATCH 164/297] move things around a little bit --- .../browser/goToDeclaration.ts | 2 +- .../browser/referenceSearch.ts | 244 +---------------- .../browser/referencesController.ts | 251 ++++++++++++++++++ ...renceSearchModel.ts => referencesModel.ts} | 10 +- ...eSearchWidget.css => referencesWidget.css} | 0 ...nceSearchWidget.ts => referencesWidget.ts} | 12 +- 6 files changed, 273 insertions(+), 246 deletions(-) create mode 100644 src/vs/editor/contrib/referenceSearch/browser/referencesController.ts rename src/vs/editor/contrib/referenceSearch/browser/{referenceSearchModel.ts => referencesModel.ts} (94%) rename src/vs/editor/contrib/referenceSearch/browser/{referenceSearchWidget.css => referencesWidget.css} (100%) rename src/vs/editor/contrib/referenceSearch/browser/{referenceSearchWidget.ts => referencesWidget.ts} (98%) diff --git a/src/vs/editor/contrib/goToDeclaration/browser/goToDeclaration.ts b/src/vs/editor/contrib/goToDeclaration/browser/goToDeclaration.ts index d17b61e1809..2fa5347b59c 100644 --- a/src/vs/editor/contrib/goToDeclaration/browser/goToDeclaration.ts +++ b/src/vs/editor/contrib/goToDeclaration/browser/goToDeclaration.ts @@ -30,7 +30,7 @@ import {tokenizeToHtmlContent} from 'vs/editor/common/modes/textToHtmlTokenizer' import {ICodeEditor, IEditorMouseEvent, IMouseTarget} from 'vs/editor/browser/editorBrowser'; import {EditorBrowserRegistry} from 'vs/editor/browser/editorBrowserExtensions'; import {getDeclarationsAtPosition} from 'vs/editor/contrib/goToDeclaration/common/goToDeclaration'; -import {ReferencesController} from 'vs/editor/contrib/referenceSearch/browser/referenceSearch'; +import {ReferencesController} from 'vs/editor/contrib/referenceSearch/browser/referencesController'; export class DefinitionActionConfig { diff --git a/src/vs/editor/contrib/referenceSearch/browser/referenceSearch.ts b/src/vs/editor/contrib/referenceSearch/browser/referenceSearch.ts index ad0c6923141..bcef373c7b8 100644 --- a/src/vs/editor/contrib/referenceSearch/browser/referenceSearch.ts +++ b/src/vs/editor/contrib/referenceSearch/browser/referenceSearch.ts @@ -5,21 +5,13 @@ 'use strict'; import * as nls from 'vs/nls'; -import {isFalsyOrEmpty} from 'vs/base/common/arrays'; -import {onUnexpectedError} from 'vs/base/common/errors'; import {KeyCode, KeyMod} from 'vs/base/common/keyCodes'; -import {cAll} from 'vs/base/common/lifecycle'; -import Severity from 'vs/base/common/severity'; import URI from 'vs/base/common/uri'; import {TPromise} from 'vs/base/common/winjs.base'; import {IEditorService} from 'vs/platform/editor/common/editor'; -import {IInstantiationService, optional} from 'vs/platform/instantiation/common/instantiation'; -import {ICommandHandler, IKeybindingContextKey, IKeybindingService, KbExpr} from 'vs/platform/keybinding/common/keybindingService'; +import {optional} from 'vs/platform/instantiation/common/instantiation'; +import {ICommandHandler, IKeybindingService, KbExpr} from 'vs/platform/keybinding/common/keybindingService'; import {KeybindingsRegistry} from 'vs/platform/keybinding/common/keybindingsRegistry'; -import {IMessageService} from 'vs/platform/message/common/message'; -import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry'; -import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace'; -import {IStorageService} from 'vs/platform/storage/common/storage'; import {Position} from 'vs/editor/common/core/position'; import {Range} from 'vs/editor/common/core/range'; import {EditorAction} from 'vs/editor/common/editorAction'; @@ -27,19 +19,12 @@ import {Behaviour} from 'vs/editor/common/editorActionEnablement'; import * as editorCommon from 'vs/editor/common/editorCommon'; import {CommonEditorRegistry, ContextKey, EditorActionDescriptor} from 'vs/editor/common/editorCommonExtensions'; import {IReference, ReferenceSearchRegistry} from 'vs/editor/common/modes'; -import {ICodeEditor} from 'vs/editor/browser/editorBrowser'; -import {EditorBrowserRegistry} from 'vs/editor/browser/editorBrowserExtensions'; import {IPeekViewService, getOuterEditor} from 'vs/editor/contrib/zoneWidget/browser/peekViewWidget'; import {findReferences} from '../common/referenceSearch'; -import {ReferencesModel, OneReference} from './referenceSearchModel'; -import {ReferenceWidget, LayoutData} from './referenceSearchWidget'; +import {ReferenceWidget} from './referencesWidget'; +import {ReferencesController, RequestOptions, ctxReferenceSearchVisible} from './referencesController'; import {ServicesAccessor} from 'vs/platform/instantiation/common/instantiation'; -export interface RequestOptions { - getMetaTitle(references: IReference[]): string; - onGoto(reference: IReference): TPromise; -} - const defaultReferenceSearchOptions: RequestOptions = { getMetaTitle(references: IReference[]) { return references.length > 1 && nls.localize('meta.titleReference', " – {0} references", references.length); @@ -47,221 +32,6 @@ const defaultReferenceSearchOptions: RequestOptions = { onGoto: undefined }; -export class ReferencesController implements editorCommon.IEditorContribution { - - public static ID = 'editor.contrib.referencesController'; - - private _editor: ICodeEditor; - private _widget: ReferenceWidget; - private _model: ReferencesModel; - private _requestIdPool = 0; - private _callOnClear: Function[] = []; - private _ignoreModelChangeEvent = false; - - private _startTime: number = -1; - private _referenceSearchVisible: IKeybindingContextKey; - - static getController(editor:editorCommon.ICommonCodeEditor): ReferencesController { - return editor.getContribution(ReferencesController.ID); - } - - public constructor( - editor: ICodeEditor, - @IKeybindingService keybindingService: IKeybindingService, - @IEditorService private _editorService: IEditorService, - @ITelemetryService private _telemetryService: ITelemetryService, - @IMessageService private _messageService: IMessageService, - @IInstantiationService private _instantiationService: IInstantiationService, - @IWorkspaceContextService private _contextService: IWorkspaceContextService, - @IStorageService private _storageService: IStorageService, - @optional(IPeekViewService) private _peekViewService: IPeekViewService - ) { - this._editor = editor; - this._referenceSearchVisible = keybindingService.createKey(CONTEXT_REFERENCE_SEARCH_VISIBLE, false); - } - - public getId(): string { - return ReferencesController.ID; - } - - public dispose(): void { - if (this._widget) { - this._widget.dispose(); - this._widget = null; - } - this._editor = null; - } - - public isInPeekView() : boolean { - return this._peekViewService && this._peekViewService.isActive; - } - - public closeReferenceSearch(): void { - this.clear(); - } - - public processRequest(range: editorCommon.IEditorRange, referencesPromise: TPromise, options: RequestOptions) : void { - var widgetPosition = !this._widget ? null : this._widget.position; - - // clean up from previous invocation - var widgetClosed = this.clear(); - - // Close if the position is still the same - if(widgetClosed && !!widgetPosition && range.containsPosition(widgetPosition)) { - return null; - } - - this._referenceSearchVisible.set(true); - - // close the widget on model/mode changes - this._callOnClear.push(this._editor.addListener(editorCommon.EventType.ModelModeChanged, () => { this.clear(); })); - this._callOnClear.push(this._editor.addListener(editorCommon.EventType.ModelChanged, () => { - if(!this._ignoreModelChangeEvent) { - this.clear(); - } - })); - const storageKey = 'peekViewLayout'; - const data = JSON.parse(this._storageService.get(storageKey, undefined, '{}')); - this._widget = new ReferenceWidget(this._editor, data, this._editorService, this._contextService, this._instantiationService); - this._widget.setTitle(nls.localize('labelLoading', "Loading...")); - this._widget.show(range); - this._callOnClear.push(this._widget.onDidClose(() => { - referencesPromise.cancel(); - - this._storageService.store(storageKey, JSON.stringify(this._widget.layoutData)); - this._widget = null; - this.clear(); - }).dispose); - - this._callOnClear.push(this._widget.onDidSelectReference(event => { - let {element, kind} = event; - switch (kind) { - case 'side': - case 'open': - this._openReference(element, kind === 'side'); - break; - case 'goto': - if (options.onGoto) { - options.onGoto(element); - } else { - this._gotoReference(element); - } - break; - } - }).dispose); - - var requestId = ++this._requestIdPool, - editorModel = this._editor.getModel(); - - var timer = this._telemetryService.timedPublicLog('findReferences', { - mode: editorModel.getMode().getId() - }); - - referencesPromise.then(references => { - - // still current request? widget still open? - if(requestId !== this._requestIdPool || !this._widget) { - timer.stop(); - return; - } - - // has a result - if (isFalsyOrEmpty(references)) { - this._widget.showMessage(nls.localize('noResults', "No results")); - timer.stop(); - return; - } - - // create result model - this._model = new ReferencesModel(references, this._editorService); - - // show widget - this._startTime = Date.now(); - if (this._widget) { - this._widget.setMetaTitle(options.getMetaTitle(references)); - this._widget.setModel(this._model); - } - timer.stop(); - - }, (error:any) => { - this._messageService.show(Severity.Error, error); - timer.stop(); - }); - } - - private clear(): boolean { - - if (this._startTime !== -1) { - this._telemetryService.publicLog('zoneWidgetShown', { - mode: 'reference search', - elapsedTime: Date.now() - this._startTime - }); - this._startTime = -1; - } - - var result = false; - if (this._widget) { - this._widget.dispose(); - this._widget = null; - result = true; - } - - this._referenceSearchVisible.reset(); - - cAll(this._callOnClear); - - this._model = null; - - this._editor.focus(); - this._requestIdPool += 1; // Cancel pending requests - return result; - } - - private _gotoReference(ref: OneReference): void { - this._ignoreModelChangeEvent = true; - const {resource, range} = ref; - - this._editorService.openEditor({ - resource, - options: { selection: range } - }).done(openedEditor => { - this._ignoreModelChangeEvent = false; - - if (!openedEditor || openedEditor.getControl() !== this._editor) { - // TODO@Alex TODO@Joh - // when opening the current reference we might end up - // in a different editor instance. that means we also have - // a different instance of this reference search controller - // and cannot hold onto the widget (which likely doesn't - // exist). Instead of bailing out we should find the - // 'sister' action and pass our current model on to it. - this.clear(); - return; - } - - this._widget.show(range); - this._widget.focus(); - - }, (err) => { - this._ignoreModelChangeEvent = false; - onUnexpectedError(err); - }); - } - - private _openReference(ref: OneReference, sideBySide: boolean): void { - const {resource, range} = ref; - this._editorService.openEditor({ - resource, - options: { selection: range } - }, sideBySide); - - // clear stage - if (!sideBySide) { - this.clear(); - } - } -} - export class ReferenceAction extends EditorAction { public static ID = 'editor.action.referenceSearch.trigger'; @@ -359,10 +129,10 @@ let showReferencesCommand: ICommandHandler = (accessor:ServicesAccessor, resourc }); }; -var CONTEXT_REFERENCE_SEARCH_VISIBLE = 'referenceSearchVisible'; + // register action -EditorBrowserRegistry.registerEditorContribution(ReferencesController); + CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(ReferenceAction, ReferenceAction.ID, nls.localize('references.action.name', "Show References"), { context: ContextKey.EditorTextFocus, primary: KeyMod.Shift | KeyCode.F12 @@ -403,7 +173,7 @@ KeybindingsRegistry.registerCommandDesc({ weight: CommonEditorRegistry.commandWeight(50), primary: KeyCode.Escape, secondary: [KeyMod.Shift | KeyCode.Escape], - when: KbExpr.and(KbExpr.has(CONTEXT_REFERENCE_SEARCH_VISIBLE), KbExpr.has('config.editor.dismissPeekOnEsc')), + when: KbExpr.and(KbExpr.has(ctxReferenceSearchVisible), KbExpr.has('config.editor.dismissPeekOnEsc')), handler: closeActiveReferenceSearch }); diff --git a/src/vs/editor/contrib/referenceSearch/browser/referencesController.ts b/src/vs/editor/contrib/referenceSearch/browser/referencesController.ts new file mode 100644 index 00000000000..c6b73812c64 --- /dev/null +++ b/src/vs/editor/contrib/referenceSearch/browser/referencesController.ts @@ -0,0 +1,251 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +import * as nls from 'vs/nls'; +import {isFalsyOrEmpty} from 'vs/base/common/arrays'; +import {onUnexpectedError} from 'vs/base/common/errors'; +import {cAll} from 'vs/base/common/lifecycle'; +import Severity from 'vs/base/common/severity'; +import {TPromise} from 'vs/base/common/winjs.base'; +import {IEditorService} from 'vs/platform/editor/common/editor'; +import {IInstantiationService, optional} from 'vs/platform/instantiation/common/instantiation'; +import {IKeybindingContextKey, IKeybindingService} from 'vs/platform/keybinding/common/keybindingService'; +import {IMessageService} from 'vs/platform/message/common/message'; +import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry'; +import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace'; +import {IStorageService} from 'vs/platform/storage/common/storage'; +import * as editorCommon from 'vs/editor/common/editorCommon'; +import {IReference} from 'vs/editor/common/modes'; +import {ICodeEditor} from 'vs/editor/browser/editorBrowser'; +import {EditorBrowserRegistry} from 'vs/editor/browser/editorBrowserExtensions'; +import {IPeekViewService} from 'vs/editor/contrib/zoneWidget/browser/peekViewWidget'; +import {ReferencesModel, OneReference} from './referencesModel'; +import {ReferenceWidget, LayoutData} from './referencesWidget'; + +export var ctxReferenceSearchVisible = 'referenceSearchVisible'; + +export interface RequestOptions { + getMetaTitle(references: IReference[]): string; + onGoto(reference: IReference): TPromise; +} + +export class ReferencesController implements editorCommon.IEditorContribution { + + public static ID = 'editor.contrib.referencesController'; + + private _editor: ICodeEditor; + private _widget: ReferenceWidget; + private _model: ReferencesModel; + private _requestIdPool = 0; + private _callOnClear: Function[] = []; + private _ignoreModelChangeEvent = false; + + private _startTime: number = -1; + private _referenceSearchVisible: IKeybindingContextKey; + + static getController(editor:editorCommon.ICommonCodeEditor): ReferencesController { + return editor.getContribution(ReferencesController.ID); + } + + public constructor( + editor: ICodeEditor, + @IKeybindingService keybindingService: IKeybindingService, + @IEditorService private _editorService: IEditorService, + @ITelemetryService private _telemetryService: ITelemetryService, + @IMessageService private _messageService: IMessageService, + @IInstantiationService private _instantiationService: IInstantiationService, + @IWorkspaceContextService private _contextService: IWorkspaceContextService, + @IStorageService private _storageService: IStorageService, + @optional(IPeekViewService) private _peekViewService: IPeekViewService + ) { + this._editor = editor; + this._referenceSearchVisible = keybindingService.createKey(ctxReferenceSearchVisible, false); + } + + public getId(): string { + return ReferencesController.ID; + } + + public dispose(): void { + if (this._widget) { + this._widget.dispose(); + this._widget = null; + } + this._editor = null; + } + + public isInPeekView() : boolean { + return this._peekViewService && this._peekViewService.isActive; + } + + public closeReferenceSearch(): void { + this.clear(); + } + + public processRequest(range: editorCommon.IEditorRange, referencesPromise: TPromise, options: RequestOptions) : void { + var widgetPosition = !this._widget ? null : this._widget.position; + + // clean up from previous invocation + var widgetClosed = this.clear(); + + // Close if the position is still the same + if(widgetClosed && !!widgetPosition && range.containsPosition(widgetPosition)) { + return null; + } + + this._referenceSearchVisible.set(true); + + // close the widget on model/mode changes + this._callOnClear.push(this._editor.addListener(editorCommon.EventType.ModelModeChanged, () => { this.clear(); })); + this._callOnClear.push(this._editor.addListener(editorCommon.EventType.ModelChanged, () => { + if(!this._ignoreModelChangeEvent) { + this.clear(); + } + })); + const storageKey = 'peekViewLayout'; + const data = JSON.parse(this._storageService.get(storageKey, undefined, '{}')); + this._widget = new ReferenceWidget(this._editor, data, this._editorService, this._contextService, this._instantiationService); + this._widget.setTitle(nls.localize('labelLoading', "Loading...")); + this._widget.show(range); + this._callOnClear.push(this._widget.onDidClose(() => { + referencesPromise.cancel(); + + this._storageService.store(storageKey, JSON.stringify(this._widget.layoutData)); + this._widget = null; + this.clear(); + }).dispose); + + this._callOnClear.push(this._widget.onDidSelectReference(event => { + let {element, kind} = event; + switch (kind) { + case 'side': + case 'open': + this._openReference(element, kind === 'side'); + break; + case 'goto': + if (options.onGoto) { + options.onGoto(element); + } else { + this._gotoReference(element); + } + break; + } + }).dispose); + + var requestId = ++this._requestIdPool, + editorModel = this._editor.getModel(); + + var timer = this._telemetryService.timedPublicLog('findReferences', { + mode: editorModel.getMode().getId() + }); + + referencesPromise.then(references => { + + // still current request? widget still open? + if(requestId !== this._requestIdPool || !this._widget) { + timer.stop(); + return; + } + + // has a result + if (isFalsyOrEmpty(references)) { + this._widget.showMessage(nls.localize('noResults', "No results")); + timer.stop(); + return; + } + + // create result model + this._model = new ReferencesModel(references); + + // show widget + this._startTime = Date.now(); + if (this._widget) { + this._widget.setMetaTitle(options.getMetaTitle(references)); + this._widget.setModel(this._model); + } + timer.stop(); + + }, (error:any) => { + this._messageService.show(Severity.Error, error); + timer.stop(); + }); + } + + private clear(): boolean { + + if (this._startTime !== -1) { + this._telemetryService.publicLog('zoneWidgetShown', { + mode: 'reference search', + elapsedTime: Date.now() - this._startTime + }); + this._startTime = -1; + } + + var result = false; + if (this._widget) { + this._widget.dispose(); + this._widget = null; + result = true; + } + + this._referenceSearchVisible.reset(); + + cAll(this._callOnClear); + + this._model = null; + + this._editor.focus(); + this._requestIdPool += 1; // Cancel pending requests + return result; + } + + private _gotoReference(ref: OneReference): void { + this._ignoreModelChangeEvent = true; + const {resource, range} = ref; + + this._editorService.openEditor({ + resource, + options: { selection: range } + }).done(openedEditor => { + this._ignoreModelChangeEvent = false; + + if (!openedEditor || openedEditor.getControl() !== this._editor) { + // TODO@Alex TODO@Joh + // when opening the current reference we might end up + // in a different editor instance. that means we also have + // a different instance of this reference search controller + // and cannot hold onto the widget (which likely doesn't + // exist). Instead of bailing out we should find the + // 'sister' action and pass our current model on to it. + this.clear(); + return; + } + + this._widget.show(range); + this._widget.focus(); + + }, (err) => { + this._ignoreModelChangeEvent = false; + onUnexpectedError(err); + }); + } + + private _openReference(ref: OneReference, sideBySide: boolean): void { + const {resource, range} = ref; + this._editorService.openEditor({ + resource, + options: { selection: range } + }, sideBySide); + + // clear stage + if (!sideBySide) { + this.clear(); + } + } +} + + +EditorBrowserRegistry.registerEditorContribution(ReferencesController); \ No newline at end of file diff --git a/src/vs/editor/contrib/referenceSearch/browser/referenceSearchModel.ts b/src/vs/editor/contrib/referenceSearch/browser/referencesModel.ts similarity index 94% rename from src/vs/editor/contrib/referenceSearch/browser/referenceSearchModel.ts rename to src/vs/editor/contrib/referenceSearch/browser/referencesModel.ts index 7e54ddba5e9..6559983ccd4 100644 --- a/src/vs/editor/contrib/referenceSearch/browser/referenceSearchModel.ts +++ b/src/vs/editor/contrib/referenceSearch/browser/referencesModel.ts @@ -97,7 +97,7 @@ export class FileReferences { private _preview: FilePreview; private _resolved: boolean; - constructor(private _parent: ReferencesModel, private _resource: URI, private _editorService: IEditorService) { + constructor(private _parent: ReferencesModel, private _resource: URI) { this._children = []; } @@ -129,13 +129,13 @@ export class FileReferences { return this._preview; } - public resolve(): TPromise { + public resolve(editorService: IEditorService): TPromise { if (this._resolved) { return TPromise.as(this); } - return this._editorService.resolveEditorModel({ resource: this._resource }).then(model => { + return editorService.resolveEditorModel({ resource: this._resource }).then(model => { this._preview = new FilePreview((model.textEditorModel).getValue()); this._resolved = true; return this; @@ -150,7 +150,7 @@ export class ReferencesModel { onDidChangeReferenceRange: Event = fromEventEmitter(this._eventBus, 'ref/changed'); - constructor(references: IReference[], editorService: IEditorService) { + constructor(references: IReference[]) { let referencesByFile: { [n: string]: FileReferences } = Object.create(null); let seen: { [n: string]: boolean } = Object.create(null); @@ -162,7 +162,7 @@ export class ReferencesModel { seen[hash] = true; let resource = reference.resource; - let fileReferences = new FileReferences(this, resource, editorService); + let fileReferences = new FileReferences(this, resource); fileReferences = collections.lookupOrInsert(referencesByFile, fileReferences.id, fileReferences); fileReferences.children.push(new OneReference(fileReferences, reference.range, this._eventBus)); diff --git a/src/vs/editor/contrib/referenceSearch/browser/referenceSearchWidget.css b/src/vs/editor/contrib/referenceSearch/browser/referencesWidget.css similarity index 100% rename from src/vs/editor/contrib/referenceSearch/browser/referenceSearchWidget.css rename to src/vs/editor/contrib/referenceSearch/browser/referencesWidget.css diff --git a/src/vs/editor/contrib/referenceSearch/browser/referenceSearchWidget.ts b/src/vs/editor/contrib/referenceSearch/browser/referencesWidget.ts similarity index 98% rename from src/vs/editor/contrib/referenceSearch/browser/referenceSearchWidget.ts rename to src/vs/editor/contrib/referenceSearch/browser/referencesWidget.ts index 8445015f46d..0c00764da05 100644 --- a/src/vs/editor/contrib/referenceSearch/browser/referenceSearchWidget.ts +++ b/src/vs/editor/contrib/referenceSearch/browser/referencesWidget.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import 'vs/css!./referenceSearchWidget'; +import 'vs/css!./referencesWidget'; import * as nls from 'vs/nls'; import * as collections from 'vs/base/common/collections'; import {onUnexpectedError} from 'vs/base/common/errors'; @@ -36,7 +36,7 @@ import {Model} from 'vs/editor/common/model/model'; import {ICodeEditor, IMouseTarget} from 'vs/editor/browser/editorBrowser'; import {EmbeddedCodeEditorWidget} from 'vs/editor/browser/widget/embeddedCodeEditorWidget'; import {PeekViewWidget, IPeekViewService} from 'vs/editor/contrib/zoneWidget/browser/peekViewWidget'; -import {FileReferences, OneReference, ReferencesModel} from './referenceSearchModel'; +import {FileReferences, OneReference, ReferencesModel} from './referencesModel'; class DecorationsManager implements IDisposable { @@ -163,6 +163,12 @@ class DecorationsManager implements IDisposable { class DataSource implements tree.IDataSource { + constructor( + @IEditorService private _editorService: IEditorService + ) { + // + } + public getId(tree:tree.ITree, element:any):string { if(element instanceof ReferencesModel) { return 'root'; @@ -181,7 +187,7 @@ class DataSource implements tree.IDataSource { if(element instanceof ReferencesModel) { return TPromise.as(( element).children); } else if(element instanceof FileReferences) { - return ( element).resolve().then(val => val.children); + return ( element).resolve(this._editorService).then(val => val.children); } else { return TPromise.as([]); } From 564c04b8c14af9903716cc6ff59f6b233cfa815b Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 13 May 2016 17:59:55 +0200 Subject: [PATCH 165/297] more cleanup and better default selection for references/definitions, #5893 --- src/vs/editor/common/core/range.ts | 2 +- .../browser/goToDeclaration.ts | 9 +- .../browser/referenceSearch.ts | 25 ++-- .../browser/referencesController.ts | 132 ++++++++---------- .../browser/referencesModel.ts | 108 +++++++------- .../browser/referencesWidget.ts | 37 ++--- 6 files changed, 154 insertions(+), 159 deletions(-) diff --git a/src/vs/editor/common/core/range.ts b/src/vs/editor/common/core/range.ts index 31742f90e79..ffd19f11276 100644 --- a/src/vs/editor/common/core/range.ts +++ b/src/vs/editor/common/core/range.ts @@ -224,7 +224,7 @@ export class Range implements IEditorRange { * A function that compares ranges, useful for sorting ranges * It will first compare ranges on the startPosition and then on the endPosition */ - public static compareRangesUsingStarts(a:IEditorRange, b:IEditorRange): number { + public static compareRangesUsingStarts(a:IRange, b:IRange): number { let aStartLineNumber = a.startLineNumber|0; let bStartLineNumber = b.startLineNumber|0; let aStartColumn = a.startColumn|0; diff --git a/src/vs/editor/contrib/goToDeclaration/browser/goToDeclaration.ts b/src/vs/editor/contrib/goToDeclaration/browser/goToDeclaration.ts index 2fa5347b59c..1b2094af88e 100644 --- a/src/vs/editor/contrib/goToDeclaration/browser/goToDeclaration.ts +++ b/src/vs/editor/contrib/goToDeclaration/browser/goToDeclaration.ts @@ -31,6 +31,7 @@ import {ICodeEditor, IEditorMouseEvent, IMouseTarget} from 'vs/editor/browser/ed import {EditorBrowserRegistry} from 'vs/editor/browser/editorBrowserExtensions'; import {getDeclarationsAtPosition} from 'vs/editor/contrib/goToDeclaration/common/goToDeclaration'; import {ReferencesController} from 'vs/editor/contrib/referenceSearch/browser/referencesController'; +import {ReferencesModel} from 'vs/editor/contrib/referenceSearch/browser/referencesModel'; export class DefinitionActionConfig { @@ -145,12 +146,12 @@ export class DefinitionAction extends EditorAction { private _openInPeek(target: editorCommon.ICommonCodeEditor, references: IReference[]) { let controller = ReferencesController.getController(target); - controller.processRequest(target.getSelection(), TPromise.as(references), { - getMetaTitle: (references) => { - return references.length > 1 && nls.localize('meta.title', " – {0} definitions", references.length); + controller.toggleWidget(target.getSelection(), TPromise.as(new ReferencesModel(references)), { + getMetaTitle: (model) => { + return model.references.length > 1 && nls.localize('meta.title', " – {0} definitions", model.references.length); }, onGoto: (reference) => { - controller.closeReferenceSearch(); + controller.closeWidget(); return this._openReference(reference, false); } }); diff --git a/src/vs/editor/contrib/referenceSearch/browser/referenceSearch.ts b/src/vs/editor/contrib/referenceSearch/browser/referenceSearch.ts index bcef373c7b8..cf5d4c201f7 100644 --- a/src/vs/editor/contrib/referenceSearch/browser/referenceSearch.ts +++ b/src/vs/editor/contrib/referenceSearch/browser/referenceSearch.ts @@ -23,13 +23,13 @@ import {IPeekViewService, getOuterEditor} from 'vs/editor/contrib/zoneWidget/bro import {findReferences} from '../common/referenceSearch'; import {ReferenceWidget} from './referencesWidget'; import {ReferencesController, RequestOptions, ctxReferenceSearchVisible} from './referencesController'; +import {ReferencesModel} from './referencesModel'; import {ServicesAccessor} from 'vs/platform/instantiation/common/instantiation'; const defaultReferenceSearchOptions: RequestOptions = { - getMetaTitle(references: IReference[]) { - return references.length > 1 && nls.localize('meta.titleReference', " – {0} references", references.length); - }, - onGoto: undefined + getMetaTitle(model) { + return model.references.length > 1 && nls.localize('meta.titleReference', " – {0} references", model.references.length); + } }; export class ReferenceAction extends EditorAction { @@ -82,9 +82,9 @@ export class ReferenceAction extends EditorAction { public run():TPromise { let range = this.editor.getSelection(); let model = this.editor.getModel(); - let request = findReferences(model, range.getStartPosition()); + let references = findReferences(model, range.getStartPosition()).then(references => new ReferencesModel(references)); let controller = ReferencesController.getController(this.editor); - return TPromise.as(controller.processRequest(range, request, defaultReferenceSearchOptions)).then(() => true); + return TPromise.as(controller.toggleWidget(range, references, defaultReferenceSearchOptions)).then(() => true); } } @@ -104,10 +104,10 @@ let findReferencesCommand: ICommandHandler = (accessor:ServicesAccessor, resourc return; } - let request = findReferences(control.getModel(), position); + let references = findReferences(control.getModel(), position).then(references => new ReferencesModel(references)); let controller = ReferencesController.getController(control); let range = new Range(position.lineNumber, position.column, position.lineNumber, position.column); - return TPromise.as(controller.processRequest(range, request, defaultReferenceSearchOptions)); + return TPromise.as(controller.toggleWidget(range, references, defaultReferenceSearchOptions)); }); }; @@ -124,8 +124,11 @@ let showReferencesCommand: ICommandHandler = (accessor:ServicesAccessor, resourc } let controller = ReferencesController.getController(control); - let range = Position.asEmptyRange(position); - return TPromise.as(controller.processRequest(Range.lift(range), TPromise.as(references), defaultReferenceSearchOptions)).then(() => true); + + return TPromise.as(controller.toggleWidget( + Range.lift(Position.asEmptyRange(position)), + TPromise.as(new ReferencesModel(references)), + defaultReferenceSearchOptions)).then(() => true); }); }; @@ -164,7 +167,7 @@ function closeActiveReferenceSearch(accessor, args) { var outerEditor = getOuterEditor(accessor, args); if (outerEditor) { var controller = ReferencesController.getController(outerEditor); - controller.closeReferenceSearch(); + controller.closeWidget(); } } diff --git a/src/vs/editor/contrib/referenceSearch/browser/referencesController.ts b/src/vs/editor/contrib/referenceSearch/browser/referencesController.ts index c6b73812c64..764080e8d02 100644 --- a/src/vs/editor/contrib/referenceSearch/browser/referencesController.ts +++ b/src/vs/editor/contrib/referenceSearch/browser/referencesController.ts @@ -5,9 +5,8 @@ 'use strict'; import * as nls from 'vs/nls'; -import {isFalsyOrEmpty} from 'vs/base/common/arrays'; import {onUnexpectedError} from 'vs/base/common/errors'; -import {cAll} from 'vs/base/common/lifecycle'; +import {IDisposable, dispose} from 'vs/base/common/lifecycle'; import Severity from 'vs/base/common/severity'; import {TPromise} from 'vs/base/common/winjs.base'; import {IEditorService} from 'vs/platform/editor/common/editor'; @@ -18,18 +17,17 @@ import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry'; import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace'; import {IStorageService} from 'vs/platform/storage/common/storage'; import * as editorCommon from 'vs/editor/common/editorCommon'; -import {IReference} from 'vs/editor/common/modes'; import {ICodeEditor} from 'vs/editor/browser/editorBrowser'; import {EditorBrowserRegistry} from 'vs/editor/browser/editorBrowserExtensions'; import {IPeekViewService} from 'vs/editor/contrib/zoneWidget/browser/peekViewWidget'; import {ReferencesModel, OneReference} from './referencesModel'; import {ReferenceWidget, LayoutData} from './referencesWidget'; -export var ctxReferenceSearchVisible = 'referenceSearchVisible'; +export const ctxReferenceSearchVisible = 'referenceSearchVisible'; export interface RequestOptions { - getMetaTitle(references: IReference[]): string; - onGoto(reference: IReference): TPromise; + getMetaTitle(model: ReferencesModel): string; + onGoto?: (reference: OneReference) => TPromise; } export class ReferencesController implements editorCommon.IEditorContribution { @@ -40,10 +38,9 @@ export class ReferencesController implements editorCommon.IEditorContribution { private _widget: ReferenceWidget; private _model: ReferencesModel; private _requestIdPool = 0; - private _callOnClear: Function[] = []; + private _disposables: IDisposable[] = []; private _ignoreModelChangeEvent = false; - private _startTime: number = -1; private _referenceSearchVisible: IKeybindingContextKey; static getController(editor:editorCommon.ICommonCodeEditor): ReferencesController { @@ -77,32 +74,25 @@ export class ReferencesController implements editorCommon.IEditorContribution { this._editor = null; } - public isInPeekView() : boolean { - return this._peekViewService && this._peekViewService.isActive; - } + public toggleWidget(range: editorCommon.IEditorRange, modelPromise: TPromise, options: RequestOptions) : void { - public closeReferenceSearch(): void { - this.clear(); - } - - public processRequest(range: editorCommon.IEditorRange, referencesPromise: TPromise, options: RequestOptions) : void { - var widgetPosition = !this._widget ? null : this._widget.position; - - // clean up from previous invocation - var widgetClosed = this.clear(); - - // Close if the position is still the same - if(widgetClosed && !!widgetPosition && range.containsPosition(widgetPosition)) { + // close current widget and return early is position didn't change + let widgetPosition: editorCommon.IPosition; + if (this._widget) { + widgetPosition = this._widget.position; + } + this.closeWidget(); + if(!!widgetPosition && range.containsPosition(widgetPosition)) { return null; } this._referenceSearchVisible.set(true); // close the widget on model/mode changes - this._callOnClear.push(this._editor.addListener(editorCommon.EventType.ModelModeChanged, () => { this.clear(); })); - this._callOnClear.push(this._editor.addListener(editorCommon.EventType.ModelChanged, () => { + this._disposables.push(this._editor.addListener2(editorCommon.EventType.ModelModeChanged, () => { this.closeWidget(); })); + this._disposables.push(this._editor.addListener2(editorCommon.EventType.ModelChanged, () => { if(!this._ignoreModelChangeEvent) { - this.clear(); + this.closeWidget(); } })); const storageKey = 'peekViewLayout'; @@ -110,15 +100,15 @@ export class ReferencesController implements editorCommon.IEditorContribution { this._widget = new ReferenceWidget(this._editor, data, this._editorService, this._contextService, this._instantiationService); this._widget.setTitle(nls.localize('labelLoading', "Loading...")); this._widget.show(range); - this._callOnClear.push(this._widget.onDidClose(() => { - referencesPromise.cancel(); + this._disposables.push(this._widget.onDidClose(() => { + modelPromise.cancel(); this._storageService.store(storageKey, JSON.stringify(this._widget.layoutData)); this._widget = null; - this.clear(); - }).dispose); + this.closeWidget(); + })); - this._callOnClear.push(this._widget.onDidSelectReference(event => { + this._disposables.push(this._widget.onDidSelectReference(event => { let {element, kind} = event; switch (kind) { case 'side': @@ -133,73 +123,63 @@ export class ReferencesController implements editorCommon.IEditorContribution { } break; } - }).dispose); + })); - var requestId = ++this._requestIdPool, - editorModel = this._editor.getModel(); - - var timer = this._telemetryService.timedPublicLog('findReferences', { - mode: editorModel.getMode().getId() + const requestId = ++this._requestIdPool; + const timer = this._telemetryService.timedPublicLog('findReferences', { + mode: this._editor.getModel().getMode().getId() }); - referencesPromise.then(references => { + modelPromise.then(model => { // still current request? widget still open? - if(requestId !== this._requestIdPool || !this._widget) { - timer.stop(); + if (requestId !== this._requestIdPool || !this._widget) { return; } + this._model = model; - // has a result - if (isFalsyOrEmpty(references)) { - this._widget.showMessage(nls.localize('noResults', "No results")); - timer.stop(); - return; - } - - // create result model - this._model = new ReferencesModel(references); + // measure time it stays open + const startTime = Date.now(); + this._disposables.push({ + dispose: () => { + this._telemetryService.publicLog('zoneWidgetShown', { + mode: 'reference search', + elapsedTime: Date.now() - startTime + }); + } + }); // show widget - this._startTime = Date.now(); - if (this._widget) { - this._widget.setMetaTitle(options.getMetaTitle(references)); - this._widget.setModel(this._model); - } - timer.stop(); + return this._widget.setModel(this._model).then(() => { - }, (error:any) => { + // set title + this._widget.setMetaTitle(options.getMetaTitle(model)); + + // set 'best' selection + let uri = this._editor.getModel().getAssociatedResource(); + let pos = { lineNumber: range.startLineNumber, column: range.startColumn }; + let selection = this._model.nearestReference(uri, pos); + return this._widget.setSelection(selection); + }); + + }, error => { this._messageService.show(Severity.Error, error); + + }).done(() => { timer.stop(); }); } - private clear(): boolean { - - if (this._startTime !== -1) { - this._telemetryService.publicLog('zoneWidgetShown', { - mode: 'reference search', - elapsedTime: Date.now() - this._startTime - }); - this._startTime = -1; - } - - var result = false; + public closeWidget(): void { if (this._widget) { this._widget.dispose(); this._widget = null; - result = true; } - this._referenceSearchVisible.reset(); - - cAll(this._callOnClear); - + this._disposables = dispose(this._disposables); this._model = null; - this._editor.focus(); this._requestIdPool += 1; // Cancel pending requests - return result; } private _gotoReference(ref: OneReference): void { @@ -220,7 +200,7 @@ export class ReferencesController implements editorCommon.IEditorContribution { // and cannot hold onto the widget (which likely doesn't // exist). Instead of bailing out we should find the // 'sister' action and pass our current model on to it. - this.clear(); + this.closeWidget(); return; } @@ -242,7 +222,7 @@ export class ReferencesController implements editorCommon.IEditorContribution { // clear stage if (!sideBySide) { - this.clear(); + this.closeWidget(); } } } diff --git a/src/vs/editor/contrib/referenceSearch/browser/referencesModel.ts b/src/vs/editor/contrib/referenceSearch/browser/referencesModel.ts index 6559983ccd4..e281f462bd5 100644 --- a/src/vs/editor/contrib/referenceSearch/browser/referencesModel.ts +++ b/src/vs/editor/contrib/referenceSearch/browser/referencesModel.ts @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import * as collections from 'vs/base/common/collections'; import {EventEmitter} from 'vs/base/common/eventEmitter'; import Event, {fromEventEmitter} from 'vs/base/common/event'; import {basename, dirname} from 'vs/base/common/paths'; @@ -143,89 +142,98 @@ export class FileReferences { } } -export class ReferencesModel { +export class ReferencesModel { - private _references: FileReferences[]; + private _groups: FileReferences[] = []; + private _references: OneReference[] = []; private _eventBus = new EventEmitter(); onDidChangeReferenceRange: Event = fromEventEmitter(this._eventBus, 'ref/changed'); constructor(references: IReference[]) { - let referencesByFile: { [n: string]: FileReferences } = Object.create(null); - let seen: { [n: string]: boolean } = Object.create(null); + // grouping and sorting + references.sort(ReferencesModel._compareReferences); - references.forEach(reference => { - - let hash = ReferencesModel._hash(reference); - if (!seen[hash]) { - seen[hash] = true; - - let resource = reference.resource; - let fileReferences = new FileReferences(this, resource); - - fileReferences = collections.lookupOrInsert(referencesByFile, fileReferences.id, fileReferences); - fileReferences.children.push(new OneReference(fileReferences, reference.range, this._eventBus)); + let current: FileReferences; + for (let ref of references) { + if (!current || current.resource.toString() !== ref.resource.toString()) { + // new group + current = new FileReferences(this, ref.resource); + this.groups.push(current); } - }); - this._references = collections.values(referencesByFile); - this._references.sort(ReferencesModel._compare); + // append, check for equality first! + if (current.children.length === 0 + || !Range.equalsRange(ref.range, current.children[current.children.length - 1].range)) { + + let oneRef = new OneReference(current, ref.range, this._eventBus); + this._references.push(oneRef); + current.children.push(oneRef); + } + } } - public get children(): FileReferences[] { + public get empty(): boolean { + return this._groups.length === 0; + } + + public get references(): OneReference[]{ return this._references; } + public get groups(): FileReferences[] { + return this._groups; + } + public nextReference(reference: OneReference): OneReference { var idx = reference.parent.children.indexOf(reference), len = reference.parent.children.length, - totalLength = reference.parent.parent.children.length; + totalLength = reference.parent.parent.groups.length; if (idx + 1 < len || totalLength === 1) { return reference.parent.children[(idx + 1) % len]; } - idx = reference.parent.parent.children.indexOf(reference.parent); + idx = reference.parent.parent.groups.indexOf(reference.parent); idx = (idx + 1) % totalLength; - return reference.parent.parent.children[idx].children[0]; + return reference.parent.parent.groups[idx].children[0]; } - public findReference(resource: URI, position: IPosition): OneReference { - for (var i = 0, len = this._references.length; i < len; i++) { - var reference = this._references[i]; - if (reference.resource.toString() !== resource.toString()) { + public nearestReference(resource: URI, position: IPosition): OneReference { + let candidate: OneReference; + let candiateDist: number; + for (let ref of this._references) { + if (ref.resource.toString() !== resource.toString()) { continue; } - var result: OneReference; - reference.children.some((element) => { - if (Range.containsPosition(element.range, position)) { - result = element; - return true; - } - return false; - }); + if (Range.containsPosition(ref.range, position)) { + // best match (!) + return ref; + } - if (result) { - return result; + let dist = + (Math.abs(ref.range.startLineNumber - position.lineNumber) * 100) + + Math.abs(ref.range.startColumn - position.column); + + if (!candidate || dist <= candiateDist) { + candidate = ref; + candiateDist = dist; } } - if (this._references.length > 0) { - return this._references[0].children[0]; + return candidate || this._references[0]; + } + + private static _compareReferences(a: IReference, b: IReference): number { + if (a.resource.toString() < b.resource.toString()) { + return -1; + } else if (a.resource.toString() > b.resource.toString()) { + return 1; + } else { + return Range.compareRangesUsingStarts(a.range, b.range); } - return null; - } - - private static _hash(reference: IReference): string { - let {startLineNumber, startColumn, endLineNumber, endColumn} = reference.range; - return [reference.resource.toString(), - startLineNumber, startColumn, endLineNumber, endColumn].join(','); - } - - private static _compare(a: FileReferences, b: FileReferences): number { - return strings.localeCompare(a.directory, b.directory) || strings.localeCompare(a.name, b.name); } } diff --git a/src/vs/editor/contrib/referenceSearch/browser/referencesWidget.ts b/src/vs/editor/contrib/referenceSearch/browser/referencesWidget.ts index 0c00764da05..d184968b0c6 100644 --- a/src/vs/editor/contrib/referenceSearch/browser/referencesWidget.ts +++ b/src/vs/editor/contrib/referenceSearch/browser/referencesWidget.ts @@ -71,9 +71,9 @@ class DecorationsManager implements IDisposable { return; } - for(var i = 0, len = this.model.children.length; i < len; i++) { - if(this.model.children[i].resource.toString() === model.getAssociatedResource().toString()) { - this._addDecorations(this.model.children[i]); + for(var i = 0, len = this.model.groups.length; i < len; i++) { + if(this.model.groups[i].resource.toString() === model.getAssociatedResource().toString()) { + this._addDecorations(this.model.groups[i]); return; } } @@ -185,7 +185,7 @@ class DataSource implements tree.IDataSource { public getChildren(tree:tree.ITree, element:any):TPromise { if(element instanceof ReferencesModel) { - return TPromise.as(( element).children); + return TPromise.as(( element).groups); } else if(element instanceof FileReferences) { return ( element).resolve(this._editorService).then(val => val.children); } else { @@ -588,24 +588,28 @@ export class ReferenceWidget extends PeekViewWidget { this._preview.layout(); } - public showMessage(message: string): void { - this.setTitle(''); - this._messageContainer.innerHtml(message).show(); + public setSelection(selection: OneReference): TPromise { + return this._revealReference(selection); } - public setModel(newModel: ReferencesModel): void { + public setModel(newModel: ReferencesModel): TPromise { // clean up this._disposeOnNewModel = dispose(this._disposeOnNewModel); this._model = newModel; if (this._model) { - this._onNewModel(); + return this._onNewModel(); } } - private _onNewModel(): void { + private _onNewModel(): TPromise { + + if (this._model.empty) { + this.setTitle(''); + this._messageContainer.innerHtml(nls.localize('noResults', "No results")).show(); + return; + } this._messageContainer.hide(); - this._decorationsManager = new DecorationsManager(this._preview, this._model); this._disposeOnNewModel.push(this._decorationsManager); @@ -650,9 +654,8 @@ export class ReferenceWidget extends PeekViewWidget { this.focus(); // pick input and a reference to begin with - const input = this._model.children.length === 1 ? this._model.children[0] : this._model; - const selection = this._model.children[0].children[0]; - this._tree.setInput(input).then(() => this._revealReference(selection)); + const input = this._model.groups.length === 1 ? this._model.groups[0] : this._model; + return this._tree.setInput(input); } private _getFocusedReference(): OneReference { @@ -666,7 +669,7 @@ export class ReferenceWidget extends PeekViewWidget { } } - private _revealReference(reference: OneReference): void { + private _revealReference(reference: OneReference) { // Update widget header if (reference.resource.scheme !== Schemas.inMemory) { @@ -675,10 +678,10 @@ export class ReferenceWidget extends PeekViewWidget { this.setTitle(nls.localize('peekView.alternateTitle', "References")); } - TPromise.join([ + return TPromise.join([ this._editorService.resolveEditorModel({ resource: reference.resource }), this._tree.reveal(reference) - ]).done(values => { + ]).then(values => { if (!this._model) { // disposed return; From 695ae2ba4165a069f5708e668ac14bfd2f89d275 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 13 May 2016 10:28:25 -0700 Subject: [PATCH 166/297] Use platformio's pty.js --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 8cb04e544c7..7ad2657beaf 100644 --- a/package.json +++ b/package.json @@ -27,10 +27,10 @@ "iconv-lite": "0.4.13", "minimist": "^1.2.0", "native-keymap": "0.1.2", - "pty.js": "git+https://github.com/jeremyramin/pty.js.git#28f2667", + "pty.js": "https://github.com/platformio/pty.js/tarball/22e84bd6ef177c7c211a767564ffe64426cb8a69", "sax": "1.1.2", "semver": "4.3.6", - "term.js": "git+https://github.com/jeremyramin/term.js.git", + "term.js": "https://github.com/jeremyramin/term.js/tarball/master", "vscode-debugprotocol": "1.8.0-pre.3", "vscode-textmate": "1.0.11", "winreg": "1.2.0", From 5cb353c381dd7603476c13b9d9c7b5fef706df73 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 13 May 2016 10:28:38 -0700 Subject: [PATCH 167/297] Add dependencies to npm-shrinkwrap.json --- npm-shrinkwrap.json | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 2e50b73ddde..24d23415030 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -340,6 +340,11 @@ "from": "preserve@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz" }, + "pty.js": { + "version": "0.3.0", + "from": "https://github.com/platformio/pty.js/tarball/22e84bd6ef177c7c211a767564ffe64426cb8a69", + "resolved": "https://github.com/platformio/pty.js/tarball/22e84bd6ef177c7c211a767564ffe64426cb8a69" + }, "randomatic": { "version": "1.1.5", "from": "randomatic@>=1.1.3 <2.0.0", @@ -390,6 +395,11 @@ "from": "string_decoder@>=0.10.0 <0.11.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" }, + "term.js": { + "version": "0.0.7", + "from": "https://github.com/jeremyramin/term.js/tarball/master", + "resolved": "https://github.com/jeremyramin/term.js/tarball/master" + }, "typechecker": { "version": "2.0.8", "from": "typechecker@>=2.0.1 <2.1.0", From 18d11591a925805278a368f73f74dc306fc76c3d Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 13 May 2016 10:59:14 -0700 Subject: [PATCH 168/297] Fix integrated terminal scrollbar after merge --- .../workbench/parts/terminal/node/terminalPanel.ts | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/parts/terminal/node/terminalPanel.ts b/src/vs/workbench/parts/terminal/node/terminalPanel.ts index 93ee7cc86eb..ace17784b3a 100644 --- a/src/vs/workbench/parts/terminal/node/terminalPanel.ts +++ b/src/vs/workbench/parts/terminal/node/terminalPanel.ts @@ -14,8 +14,8 @@ import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry'; import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace'; import {ITerminalConfiguration, TERMINAL_PANEL_ID} from 'vs/workbench/parts/terminal/common/terminal'; import {Panel} from 'vs/workbench/browser/panel'; -import {ScrollableElement} from 'vs/base/browser/ui/scrollbar/scrollableElementImpl'; -import {DomNodeScrollable} from 'vs/base/browser/ui/scrollbar/domNodeScrollable'; +import {DomScrollableElement} from 'vs/base/browser/ui/scrollbar/scrollableElement'; +import {ScrollbarVisibility} from 'vs/base/browser/ui/scrollbar/scrollableElementOptions'; const TERMINAL_CHAR_WIDTH = 8; const TERMINAL_CHAR_HEIGHT = 18; @@ -61,8 +61,12 @@ export class TerminalPanel extends Panel { }); this.terminalDomElement = document.createElement('div'); this.parentDomElement.classList.add('integrated-terminal'); - let terminalScrollable = new DomNodeScrollable(this.terminalDomElement); - let terminalContainer = new ScrollableElement(this.terminalDomElement, terminalScrollable, { horizontal: 'hidden', vertical: 'auto' }); + let terminalScrollable = new DomScrollableElement(this.terminalDomElement, { + canUseTranslate3d: false, + horizontal: ScrollbarVisibility.Hidden, + vertical: ScrollbarVisibility.Auto + }); + //let terminalContainer = new ScrollableElement(this.terminalDomElement, terminalScrollable, { horizontal: 'hidden', vertical: 'auto' }); this.terminal = termJs({ cursorBlink: false // term.js' blinking cursor breaks selection }); @@ -95,7 +99,7 @@ export class TerminalPanel extends Panel { }); this.terminal.open(this.terminalDomElement); - this.parentDomElement.appendChild(terminalContainer.getDomNode()); + this.parentDomElement.appendChild(terminalScrollable.getDomNode()); let config = this.configurationService.getConfiguration(); this.terminalDomElement.style.fontFamily = config.integratedTerminal.fontFamily; From 18d8a43f859a6805788d8190cff1913cacae8a14 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 13 May 2016 11:00:20 -0700 Subject: [PATCH 169/297] Remove initial col and row as it's immediately overridden --- src/vs/workbench/parts/terminal/node/terminalPanel.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/vs/workbench/parts/terminal/node/terminalPanel.ts b/src/vs/workbench/parts/terminal/node/terminalPanel.ts index ace17784b3a..54192b00377 100644 --- a/src/vs/workbench/parts/terminal/node/terminalPanel.ts +++ b/src/vs/workbench/parts/terminal/node/terminalPanel.ts @@ -55,8 +55,6 @@ export class TerminalPanel extends Panel { this.parentDomElement.innerHTML = ''; this.ptyProcess = fork(this.getShell(), [], { name: fs.existsSync('/usr/share/terminfo/x/xterm-256color') ? 'xterm-256color' : 'xterm', - cols: 80, - rows: 6, cwd: this.contextService.getWorkspace() ? this.contextService.getWorkspace().resource.fsPath : process.env.HOME }); this.terminalDomElement = document.createElement('div'); From 613777fbe60fc3bba66703db53d57385419650ce Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 13 May 2016 11:17:14 -0700 Subject: [PATCH 170/297] Move integrated terminal from node -> electron-browser --- .../media/terminal.contribution.css | 0 .../parts/terminal/{node => electron-browser}/pty.js.d.ts | 0 .../parts/terminal/{node => electron-browser}/term.js.d.ts | 0 .../{node => electron-browser}/terminal.contribution.ts | 6 +++--- .../terminal/{node => electron-browser}/terminalActions.ts | 0 .../terminal/{node => electron-browser}/terminalPanel.ts | 0 .../terminal/{node => electron-browser}/terminalService.ts | 0 src/vs/workbench/workbench.main.js | 2 +- 8 files changed, 4 insertions(+), 4 deletions(-) rename src/vs/workbench/parts/terminal/{node => electron-browser}/media/terminal.contribution.css (100%) rename src/vs/workbench/parts/terminal/{node => electron-browser}/pty.js.d.ts (100%) rename src/vs/workbench/parts/terminal/{node => electron-browser}/term.js.d.ts (100%) rename src/vs/workbench/parts/terminal/{node => electron-browser}/terminal.contribution.ts (97%) rename src/vs/workbench/parts/terminal/{node => electron-browser}/terminalActions.ts (100%) rename src/vs/workbench/parts/terminal/{node => electron-browser}/terminalPanel.ts (100%) rename src/vs/workbench/parts/terminal/{node => electron-browser}/terminalService.ts (100%) diff --git a/src/vs/workbench/parts/terminal/node/media/terminal.contribution.css b/src/vs/workbench/parts/terminal/electron-browser/media/terminal.contribution.css similarity index 100% rename from src/vs/workbench/parts/terminal/node/media/terminal.contribution.css rename to src/vs/workbench/parts/terminal/electron-browser/media/terminal.contribution.css diff --git a/src/vs/workbench/parts/terminal/node/pty.js.d.ts b/src/vs/workbench/parts/terminal/electron-browser/pty.js.d.ts similarity index 100% rename from src/vs/workbench/parts/terminal/node/pty.js.d.ts rename to src/vs/workbench/parts/terminal/electron-browser/pty.js.d.ts diff --git a/src/vs/workbench/parts/terminal/node/term.js.d.ts b/src/vs/workbench/parts/terminal/electron-browser/term.js.d.ts similarity index 100% rename from src/vs/workbench/parts/terminal/node/term.js.d.ts rename to src/vs/workbench/parts/terminal/electron-browser/term.js.d.ts diff --git a/src/vs/workbench/parts/terminal/node/terminal.contribution.ts b/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.ts similarity index 97% rename from src/vs/workbench/parts/terminal/node/terminal.contribution.ts rename to src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.ts index 2a94b34383d..b8e2425cf91 100644 --- a/src/vs/workbench/parts/terminal/node/terminal.contribution.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.ts @@ -9,8 +9,8 @@ import nls = require('vs/nls'); import {SyncActionDescriptor} from 'vs/platform/actions/common/actions'; import {registerSingleton} from 'vs/platform/instantiation/common/extensions'; import {IWorkbenchActionRegistry, Extensions as ActionExtensions} from 'vs/workbench/common/actionRegistry'; -import {TerminalService} from 'vs/workbench/parts/terminal/node/terminalService'; -import {ToggleTerminalAction} from 'vs/workbench/parts/terminal/node/terminalActions'; +import {TerminalService} from 'vs/workbench/parts/terminal/electron-browser/terminalService'; +import {ToggleTerminalAction} from 'vs/workbench/parts/terminal/electron-browser/terminalActions'; import {ITerminalService, TERMINAL_PANEL_ID, TERMINAL_DEFAULT_SHELL_UNIX_LIKE, TERMINAL_DEFAULT_SHELL_WINDOWS} from 'vs/workbench/parts/terminal/common/terminal'; import * as panel from 'vs/workbench/browser/panel'; import {Registry} from 'vs/platform/platform'; @@ -126,7 +126,7 @@ registerSingleton(ITerminalService, TerminalService); // Register Output Panel (Registry.as(panel.Extensions.Panels)).registerPanel(new panel.PanelDescriptor( - 'vs/workbench/parts/terminal/node/terminalPanel', + 'vs/workbench/parts/terminal/electron-browser/terminalPanel', 'TerminalPanel', TERMINAL_PANEL_ID, nls.localize('terminal', "Terminal"), diff --git a/src/vs/workbench/parts/terminal/node/terminalActions.ts b/src/vs/workbench/parts/terminal/electron-browser/terminalActions.ts similarity index 100% rename from src/vs/workbench/parts/terminal/node/terminalActions.ts rename to src/vs/workbench/parts/terminal/electron-browser/terminalActions.ts diff --git a/src/vs/workbench/parts/terminal/node/terminalPanel.ts b/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.ts similarity index 100% rename from src/vs/workbench/parts/terminal/node/terminalPanel.ts rename to src/vs/workbench/parts/terminal/electron-browser/terminalPanel.ts diff --git a/src/vs/workbench/parts/terminal/node/terminalService.ts b/src/vs/workbench/parts/terminal/electron-browser/terminalService.ts similarity index 100% rename from src/vs/workbench/parts/terminal/node/terminalService.ts rename to src/vs/workbench/parts/terminal/electron-browser/terminalService.ts diff --git a/src/vs/workbench/workbench.main.js b/src/vs/workbench/workbench.main.js index 9a30a1160a3..45bbb116fc7 100644 --- a/src/vs/workbench/workbench.main.js +++ b/src/vs/workbench/workbench.main.js @@ -58,7 +58,7 @@ define([ 'vs/workbench/parts/output/browser/output.contribution', - 'vs/workbench/parts/terminal/node/terminal.contribution', + 'vs/workbench/parts/terminal/electron-browser/terminal.contribution', 'vs/workbench/parts/markdown/browser/markdown.contribution', 'vs/workbench/parts/markdown/browser/markdownActions.contribution', From f48a0723fc22358d4fd56cbbb15dc951daeb66da Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 13 May 2016 11:22:41 -0700 Subject: [PATCH 171/297] Encapsulated interfaces with part/panel services in terminalService --- .../terminal/electron-browser/terminalActions.ts | 13 +------------ .../terminal/electron-browser/terminalService.ts | 11 ++++++++++- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalActions.ts b/src/vs/workbench/parts/terminal/electron-browser/terminalActions.ts index aa332ca2234..bda26557661 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminalActions.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminalActions.ts @@ -6,9 +6,7 @@ import {TPromise} from 'vs/base/common/winjs.base'; import nls = require('vs/nls'); import {Action} from 'vs/base/common/actions'; -import {IPartService} from 'vs/workbench/services/part/common/partService'; -import {IPanelService} from 'vs/workbench/services/panel/common/panelService'; -import {TERMINAL_PANEL_ID, ITerminalService} from 'vs/workbench/parts/terminal/common/terminal'; +import {ITerminalService} from 'vs/workbench/parts/terminal/common/terminal'; export class ToggleTerminalAction extends Action { @@ -17,21 +15,12 @@ export class ToggleTerminalAction extends Action { constructor( id: string, label: string, - @IPartService private partService: IPartService, - @IPanelService private panelService: IPanelService, @ITerminalService private terminalService: ITerminalService ) { super(id, label); } public run(event?: any): TPromise { - const panel = this.panelService.getActivePanel(); - if (panel && panel.getId() === TERMINAL_PANEL_ID) { - this.partService.setPanelHidden(true); - - return TPromise.as(null); - } - return this.terminalService.show(); } } \ No newline at end of file diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalService.ts b/src/vs/workbench/parts/terminal/electron-browser/terminalService.ts index 7d5c3837d96..b834d580627 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminalService.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminalService.ts @@ -5,17 +5,26 @@ import {TPromise} from 'vs/base/common/winjs.base'; import {IPanelService} from 'vs/workbench/services/panel/common/panelService'; +import {IPartService} from 'vs/workbench/services/part/common/partService'; import {ITerminalService, TERMINAL_PANEL_ID} from 'vs/workbench/parts/terminal/common/terminal'; export class TerminalService implements ITerminalService { public serviceId = ITerminalService; constructor( - @IPanelService private panelService: IPanelService + @IPanelService private panelService: IPanelService, + @IPartService private partService: IPartService ) { } public show(): TPromise { + const panel = this.panelService.getActivePanel(); + if (panel && panel.getId() === TERMINAL_PANEL_ID) { + this.partService.setPanelHidden(true); + + return TPromise.as(null); + } + return this.panelService.openPanel(TERMINAL_PANEL_ID, true); } } \ No newline at end of file From 55541cc58d28e308142ca59c74083d21ed4e1a46 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 13 May 2016 11:32:49 -0700 Subject: [PATCH 172/297] Have createTerminal execute asynchronously --- .../electron-browser/terminalPanel.ts | 101 +++++++++--------- 1 file changed, 51 insertions(+), 50 deletions(-) diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.ts b/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.ts index 54192b00377..0b2db776d05 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.ts @@ -46,62 +46,63 @@ export class TerminalPanel extends Panel { super.create(parent); this.parentDomElement = parent.getHTMLElement(); - this.createTerminal(); - return TPromise.as(null); + return this.createTerminal(); } - private createTerminal(): void { - this.parentDomElement.innerHTML = ''; - this.ptyProcess = fork(this.getShell(), [], { - name: fs.existsSync('/usr/share/terminfo/x/xterm-256color') ? 'xterm-256color' : 'xterm', - cwd: this.contextService.getWorkspace() ? this.contextService.getWorkspace().resource.fsPath : process.env.HOME - }); - this.terminalDomElement = document.createElement('div'); - this.parentDomElement.classList.add('integrated-terminal'); - let terminalScrollable = new DomScrollableElement(this.terminalDomElement, { - canUseTranslate3d: false, - horizontal: ScrollbarVisibility.Hidden, - vertical: ScrollbarVisibility.Auto - }); - //let terminalContainer = new ScrollableElement(this.terminalDomElement, terminalScrollable, { horizontal: 'hidden', vertical: 'auto' }); - this.terminal = termJs({ - cursorBlink: false // term.js' blinking cursor breaks selection - }); + private createTerminal(): TPromise { + return new TPromise(resolve => { + this.parentDomElement.innerHTML = ''; + this.ptyProcess = fork(this.getShell(), [], { + name: fs.existsSync('/usr/share/terminfo/x/xterm-256color') ? 'xterm-256color' : 'xterm', + cwd: this.contextService.getWorkspace() ? this.contextService.getWorkspace().resource.fsPath : process.env.HOME + }); + this.terminalDomElement = document.createElement('div'); + this.parentDomElement.classList.add('integrated-terminal'); + let terminalScrollable = new DomScrollableElement(this.terminalDomElement, { + canUseTranslate3d: false, + horizontal: ScrollbarVisibility.Hidden, + vertical: ScrollbarVisibility.Auto + }); + this.terminal = termJs({ + cursorBlink: false // term.js' blinking cursor breaks selection + }); - this.ptyProcess.on('data', (data) => { - this.terminal.write(data); - }); - this.terminal.on('data', (data) => { - this.ptyProcess.write(data); - return false; - }); - this.ptyProcess.on('exit', (data) => { - this.terminal.destroy(); - // TODO: When multiple terminals are supported this should do something smarter. There is - // also a weird bug here at leasy on Ubuntu 15.10 where the new terminal text does not - // repaint correctly. - this.createTerminal(); - }); - this.parentDomElement.addEventListener('mousedown', (event) => { - // Drop selection and focus terminal on Linux to enable middle button paste when click - // occurs on the selection itself. - if (event.which === 2 && platform.isLinux) { - this.focusTerminal(true); - } - }); - this.parentDomElement.addEventListener('mouseup', (event) => { - if (event.which !== 3) { - this.focusTerminal(); - } - }); + this.ptyProcess.on('data', (data) => { + this.terminal.write(data); + }); + this.terminal.on('data', (data) => { + this.ptyProcess.write(data); + return false; + }); + this.ptyProcess.on('exit', (data) => { + this.terminal.destroy(); + // TODO: When multiple terminals are supported this should do something smarter. There is + // also a weird bug here at leasy on Ubuntu 15.10 where the new terminal text does not + // repaint correctly. + this.createTerminal(); + }); + this.parentDomElement.addEventListener('mousedown', (event) => { + // Drop selection and focus terminal on Linux to enable middle button paste when click + // occurs on the selection itself. + if (event.which === 2 && platform.isLinux) { + this.focusTerminal(true); + } + }); + this.parentDomElement.addEventListener('mouseup', (event) => { + if (event.which !== 3) { + this.focusTerminal(); + } + }); - this.terminal.open(this.terminalDomElement); - this.parentDomElement.appendChild(terminalScrollable.getDomNode()); + this.terminal.open(this.terminalDomElement); + this.parentDomElement.appendChild(terminalScrollable.getDomNode()); - let config = this.configurationService.getConfiguration(); - this.terminalDomElement.style.fontFamily = config.integratedTerminal.fontFamily; - this.terminal.colors = this.getTerminalColors(); + let config = this.configurationService.getConfiguration(); + this.terminalDomElement.style.fontFamily = config.integratedTerminal.fontFamily; + this.terminal.colors = this.getTerminalColors(); + resolve(void 0); + }); } private focusTerminal(force?: boolean): void { From f39ca65cc35cd1d036887cde2ad1d70042c2e5bc Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 13 May 2016 11:39:15 -0700 Subject: [PATCH 173/297] Dispose terminal scrollbar and event listeners --- .../electron-browser/terminalPanel.ts | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.ts b/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.ts index 0b2db776d05..8f9927186b9 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.ts @@ -4,7 +4,9 @@ *--------------------------------------------------------------------------------------------*/ import termJs = require('term.js'); +import lifecycle = require('vs/base/common/lifecycle'); import fs = require('fs'); +import DOM = require('vs/base/browser/dom'); import {fork, Terminal} from 'pty.js'; import platform = require('vs/base/common/platform'); import {TPromise} from 'vs/base/common/winjs.base'; @@ -22,6 +24,7 @@ const TERMINAL_CHAR_HEIGHT = 18; export class TerminalPanel extends Panel { + private toDispose: lifecycle.IDisposable[]; private ptyProcess: Terminal; private parentDomElement: HTMLElement; private terminal; @@ -33,6 +36,7 @@ export class TerminalPanel extends Panel { @IWorkspaceContextService private contextService: IWorkspaceContextService ) { super(TERMINAL_PANEL_ID, telemetryService); + this.toDispose = []; } public layout(dimension: Dimension): void { @@ -59,11 +63,12 @@ export class TerminalPanel extends Panel { }); this.terminalDomElement = document.createElement('div'); this.parentDomElement.classList.add('integrated-terminal'); - let terminalScrollable = new DomScrollableElement(this.terminalDomElement, { + let terminalScrollbar = new DomScrollableElement(this.terminalDomElement, { canUseTranslate3d: false, horizontal: ScrollbarVisibility.Hidden, vertical: ScrollbarVisibility.Auto }); + this.toDispose.push(terminalScrollbar); this.terminal = termJs({ cursorBlink: false // term.js' blinking cursor breaks selection }); @@ -82,21 +87,21 @@ export class TerminalPanel extends Panel { // repaint correctly. this.createTerminal(); }); - this.parentDomElement.addEventListener('mousedown', (event) => { + this.toDispose.push(DOM.addDisposableListener(this.parentDomElement, 'mousedown', (event) => { // Drop selection and focus terminal on Linux to enable middle button paste when click // occurs on the selection itself. if (event.which === 2 && platform.isLinux) { this.focusTerminal(true); } - }); - this.parentDomElement.addEventListener('mouseup', (event) => { + })); + this.toDispose.push(DOM.addDisposableListener(this.parentDomElement, 'mouseup', (event) => { if (event.which !== 3) { this.focusTerminal(); } - }); + })); this.terminal.open(this.terminalDomElement); - this.parentDomElement.appendChild(terminalScrollable.getDomNode()); + this.parentDomElement.appendChild(terminalScrollbar.getDomNode()); let config = this.configurationService.getConfiguration(); this.terminalDomElement.style.fontFamily = config.integratedTerminal.fontFamily; @@ -145,4 +150,9 @@ export class TerminalPanel extends Panel { ]; return colors; } + + public dispose(): void { + this.toDispose = lifecycle.dispose(this.toDispose); + super.dispose(); + } } From 36acfe6b177614b001cb1d0cb697bcf5696085e3 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 13 May 2016 12:09:08 -0700 Subject: [PATCH 174/297] Enable integrated terminal in alpha channel only --- .../electron-browser/terminal.contribution.ts | 238 +++++++++--------- 1 file changed, 121 insertions(+), 117 deletions(-) diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.ts b/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.ts index b8e2425cf91..f805c9d9714 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.ts @@ -5,6 +5,7 @@ import 'vs/css!./media/terminal.contribution'; import nls = require('vs/nls'); +import product from 'vs/platform/product'; //import {KeyMod, KeyCode} from 'vs/base/common/keyCodes'; import {SyncActionDescriptor} from 'vs/platform/actions/common/actions'; import {registerSingleton} from 'vs/platform/instantiation/common/extensions'; @@ -16,124 +17,127 @@ import * as panel from 'vs/workbench/browser/panel'; import {Registry} from 'vs/platform/platform'; import {Extensions, IConfigurationRegistry} from 'vs/platform/configuration/common/configurationRegistry'; -let configurationRegistry = Registry.as(Extensions.Configuration); -configurationRegistry.registerConfiguration({ - 'id': 'terminal', - 'order': 100, - 'title': nls.localize('integratedTerminalConfigurationTitle', "(Experimental) Integrated terminal configuration"), - 'type': 'object', - 'properties': { - 'integratedTerminal.shell.unixLike': { - 'description': nls.localize('integratedTerminal.shell.unixLike', "The path of the shell that the terminal uses on Linux and OS X."), - 'type': 'string', - 'default': TERMINAL_DEFAULT_SHELL_UNIX_LIKE - }, - 'integratedTerminal.shell.windows': { - 'description': nls.localize('integratedTerminal.shell.windows', "The path of the shell that the terminal uses on Windows."), - 'type': 'string', - 'default': TERMINAL_DEFAULT_SHELL_WINDOWS - }, - 'integratedTerminal.fontFamily': { - 'description': nls.localize('integratedTerminal.fontFamily', "The font family used by the terminal (CSS font-family format)."), - 'type': 'string', - 'default': 'Menlo, Monaco, Consolas, "Droid Sans Mono", "Courier New", monospace, "Droid Sans Fallback"' - }, - 'integratedTerminal.ansiColors.black': { - 'description': nls.localize('integratedTerminal.ansiColors.black', "Black color for terminals that support ANSI escape sequences (format: #rrggbb)"), - 'type': 'string', - 'default': '#000000' - }, - 'integratedTerminal.ansiColors.red': { - 'description': nls.localize('integratedTerminal.ansiColors.red', "Red color for terminals that support ANSI escape sequences (format: #rrggbb)"), - 'type': 'string', - 'default': '#cd3131' - }, - 'integratedTerminal.ansiColors.green': { - 'description': nls.localize('integratedTerminal.ansiColors.green', "Green color for terminals that support ANSI escape sequences (format: #rrggbb)"), - 'type': 'string', - 'default': '#09885a' - }, - 'integratedTerminal.ansiColors.yellow': { - 'description': nls.localize('integratedTerminal.ansiColors.yellow', "Yellow color for terminals that support ANSI escape sequences (format: #rrggbb)"), - 'type': 'string', - 'default': '#e5e510' - }, - 'integratedTerminal.ansiColors.blue': { - 'description': nls.localize('integratedTerminal.ansiColors.blue', "Blue color for terminals that support ANSI escape sequences (format: #rrggbb)"), - 'type': 'string', - 'default': '#0451a5' - }, - 'integratedTerminal.ansiColors.magenta': { - 'description': nls.localize('integratedTerminal.ansiColors.magenta', "Magenta color for terminals that support ANSI escape sequences (format: #rrggbb)"), - 'type': 'string', - 'default': '#bc05bc' - }, - 'integratedTerminal.ansiColors.cyan': { - 'description': nls.localize('integratedTerminal.ansiColors.cyan', "Cyan color for terminals that support ANSI escape sequences (format: #rrggbb)"), - 'type': 'string', - 'default': '#0598bc' - }, - 'integratedTerminal.ansiColors.white': { - 'description': nls.localize('integratedTerminal.ansiColors.white', "White color for terminals that support ANSI escape sequences (format: #rrggbb)"), - 'type': 'string', - 'default': '#e5e5e5' - }, - 'integratedTerminal.ansiColors.brightBlack': { - 'description': nls.localize('integratedTerminal.ansiColors.brightBlack', "Bright black color for terminals that support ANSI escape sequences (format: #rrggbb)"), - 'type': 'string', - 'default': '#000000' - }, - 'integratedTerminal.ansiColors.brightRed': { - 'description': nls.localize('integratedTerminal.ansiColors.brightRed', "Bright red color for terminals that support ANSI escape sequences (format: #rrggbb)"), - 'type': 'string', - 'default': '#cd3131' - }, - 'integratedTerminal.ansiColors.brightGreen': { - 'description': nls.localize('integratedTerminal.ansiColors.brightGreen', "Bright green color for terminals that support ANSI escape sequences (format: #rrggbb)"), - 'type': 'string', - 'default': '#09885a' - }, - 'integratedTerminal.ansiColors.brightYellow': { - 'description': nls.localize('integratedTerminal.ansiColors.brightYellow', "Bright yellow color for terminals that support ANSI escape sequences (format: #rrggbb)"), - 'type': 'string', - 'default': '#e5e510' - }, - 'integratedTerminal.ansiColors.brightBlue': { - 'description': nls.localize('integratedTerminal.ansiColors.brightBlue', "Bright blue color for terminals that support ANSI escape sequences (format: #rrggbb)"), - 'type': 'string', - 'default': '#0451a5' - }, - 'integratedTerminal.ansiColors.brightMagenta': { - 'description': nls.localize('integratedTerminal.ansiColors.brightMagenta', "Bright magenta color for terminals that support ANSI escape sequences (format: #rrggbb)"), - 'type': 'string', - 'default': '#bc05bc' - }, - 'integratedTerminal.ansiColors.brightCyan': { - 'description': nls.localize('integratedTerminal.ansiColors.brightCyan', "Bright cyan color for terminals that support ANSI escape sequences (format: #rrggbb)"), - 'type': 'string', - 'default': '#0598bc' - }, - 'integratedTerminal.ansiColors.brightWhite': { - 'description': nls.localize('integratedTerminal.ansiColors.brightWhite', "Bright white color for terminals that support ANSI escape sequences (format: #rrggbb)"), - 'type': 'string', - 'default': '#e5e5e5' +// Only enable in the alpha channel until more stable +if (product.quality === 'alpha') { + let configurationRegistry = Registry.as(Extensions.Configuration); + configurationRegistry.registerConfiguration({ + 'id': 'terminal', + 'order': 100, + 'title': nls.localize('integratedTerminalConfigurationTitle', "(Experimental) Integrated terminal configuration"), + 'type': 'object', + 'properties': { + 'integratedTerminal.shell.unixLike': { + 'description': nls.localize('integratedTerminal.shell.unixLike', "The path of the shell that the terminal uses on Linux and OS X."), + 'type': 'string', + 'default': TERMINAL_DEFAULT_SHELL_UNIX_LIKE + }, + 'integratedTerminal.shell.windows': { + 'description': nls.localize('integratedTerminal.shell.windows', "The path of the shell that the terminal uses on Windows."), + 'type': 'string', + 'default': TERMINAL_DEFAULT_SHELL_WINDOWS + }, + 'integratedTerminal.fontFamily': { + 'description': nls.localize('integratedTerminal.fontFamily', "The font family used by the terminal (CSS font-family format)."), + 'type': 'string', + 'default': 'Menlo, Monaco, Consolas, "Droid Sans Mono", "Courier New", monospace, "Droid Sans Fallback"' + }, + 'integratedTerminal.ansiColors.black': { + 'description': nls.localize('integratedTerminal.ansiColors.black', "Black color for terminals that support ANSI escape sequences (format: #rrggbb)"), + 'type': 'string', + 'default': '#000000' + }, + 'integratedTerminal.ansiColors.red': { + 'description': nls.localize('integratedTerminal.ansiColors.red', "Red color for terminals that support ANSI escape sequences (format: #rrggbb)"), + 'type': 'string', + 'default': '#cd3131' + }, + 'integratedTerminal.ansiColors.green': { + 'description': nls.localize('integratedTerminal.ansiColors.green', "Green color for terminals that support ANSI escape sequences (format: #rrggbb)"), + 'type': 'string', + 'default': '#09885a' + }, + 'integratedTerminal.ansiColors.yellow': { + 'description': nls.localize('integratedTerminal.ansiColors.yellow', "Yellow color for terminals that support ANSI escape sequences (format: #rrggbb)"), + 'type': 'string', + 'default': '#e5e510' + }, + 'integratedTerminal.ansiColors.blue': { + 'description': nls.localize('integratedTerminal.ansiColors.blue', "Blue color for terminals that support ANSI escape sequences (format: #rrggbb)"), + 'type': 'string', + 'default': '#0451a5' + }, + 'integratedTerminal.ansiColors.magenta': { + 'description': nls.localize('integratedTerminal.ansiColors.magenta', "Magenta color for terminals that support ANSI escape sequences (format: #rrggbb)"), + 'type': 'string', + 'default': '#bc05bc' + }, + 'integratedTerminal.ansiColors.cyan': { + 'description': nls.localize('integratedTerminal.ansiColors.cyan', "Cyan color for terminals that support ANSI escape sequences (format: #rrggbb)"), + 'type': 'string', + 'default': '#0598bc' + }, + 'integratedTerminal.ansiColors.white': { + 'description': nls.localize('integratedTerminal.ansiColors.white', "White color for terminals that support ANSI escape sequences (format: #rrggbb)"), + 'type': 'string', + 'default': '#e5e5e5' + }, + 'integratedTerminal.ansiColors.brightBlack': { + 'description': nls.localize('integratedTerminal.ansiColors.brightBlack', "Bright black color for terminals that support ANSI escape sequences (format: #rrggbb)"), + 'type': 'string', + 'default': '#000000' + }, + 'integratedTerminal.ansiColors.brightRed': { + 'description': nls.localize('integratedTerminal.ansiColors.brightRed', "Bright red color for terminals that support ANSI escape sequences (format: #rrggbb)"), + 'type': 'string', + 'default': '#cd3131' + }, + 'integratedTerminal.ansiColors.brightGreen': { + 'description': nls.localize('integratedTerminal.ansiColors.brightGreen', "Bright green color for terminals that support ANSI escape sequences (format: #rrggbb)"), + 'type': 'string', + 'default': '#09885a' + }, + 'integratedTerminal.ansiColors.brightYellow': { + 'description': nls.localize('integratedTerminal.ansiColors.brightYellow', "Bright yellow color for terminals that support ANSI escape sequences (format: #rrggbb)"), + 'type': 'string', + 'default': '#e5e510' + }, + 'integratedTerminal.ansiColors.brightBlue': { + 'description': nls.localize('integratedTerminal.ansiColors.brightBlue', "Bright blue color for terminals that support ANSI escape sequences (format: #rrggbb)"), + 'type': 'string', + 'default': '#0451a5' + }, + 'integratedTerminal.ansiColors.brightMagenta': { + 'description': nls.localize('integratedTerminal.ansiColors.brightMagenta', "Bright magenta color for terminals that support ANSI escape sequences (format: #rrggbb)"), + 'type': 'string', + 'default': '#bc05bc' + }, + 'integratedTerminal.ansiColors.brightCyan': { + 'description': nls.localize('integratedTerminal.ansiColors.brightCyan', "Bright cyan color for terminals that support ANSI escape sequences (format: #rrggbb)"), + 'type': 'string', + 'default': '#0598bc' + }, + 'integratedTerminal.ansiColors.brightWhite': { + 'description': nls.localize('integratedTerminal.ansiColors.brightWhite', "Bright white color for terminals that support ANSI escape sequences (format: #rrggbb)"), + 'type': 'string', + 'default': '#e5e5e5' + } } - } -}); + }); -// Register Service -registerSingleton(ITerminalService, TerminalService); + // Register Service + registerSingleton(ITerminalService, TerminalService); -// Register Output Panel -(Registry.as(panel.Extensions.Panels)).registerPanel(new panel.PanelDescriptor( - 'vs/workbench/parts/terminal/electron-browser/terminalPanel', - 'TerminalPanel', - TERMINAL_PANEL_ID, - nls.localize('terminal', "Terminal"), - 'terminal' -)); + // Register Output Panel + (Registry.as(panel.Extensions.Panels)).registerPanel(new panel.PanelDescriptor( + 'vs/workbench/parts/terminal/electron-browser/terminalPanel', + 'TerminalPanel', + TERMINAL_PANEL_ID, + nls.localize('terminal', "Terminal"), + 'terminal' + )); -// Register toggle output action globally -let actionRegistry = Registry.as(ActionExtensions.WorkbenchActions); -// { primary: KeyMod.CtrlCmd | KeyCode.US_BACKTICK } -actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ToggleTerminalAction, ToggleTerminalAction.ID, ToggleTerminalAction.LABEL), 'View: ' + ToggleTerminalAction.LABEL, nls.localize('viewCategory', "View")); + // Register toggle output action globally + let actionRegistry = Registry.as(ActionExtensions.WorkbenchActions); + // { primary: KeyMod.CtrlCmd | KeyCode.US_BACKTICK } + actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ToggleTerminalAction, ToggleTerminalAction.ID, ToggleTerminalAction.LABEL), 'View: ' + ToggleTerminalAction.LABEL, nls.localize('viewCategory', "View")); +} \ No newline at end of file From c2c7bbd7ae02137abd2c0448186e357b02475cac Mon Sep 17 00:00:00 2001 From: Andre Weinand Date: Sat, 14 May 2016 00:07:34 +0200 Subject: [PATCH 175/297] fix extension debugging --- extensions/node-debug/node-debug.azure.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/node-debug/node-debug.azure.json b/extensions/node-debug/node-debug.azure.json index 01fb5d9123a..63c268656a8 100644 --- a/extensions/node-debug/node-debug.azure.json +++ b/extensions/node-debug/node-debug.azure.json @@ -1,6 +1,6 @@ { "account": "monacobuild", "container": "debuggers", - "zip": "2a0d6ce/node-debug.zip", + "zip": "48428c0/node-debug.zip", "output": "" } From 179fd839981d7a18eb4b8588955969fb8556c2f8 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 13 May 2016 15:12:17 -0700 Subject: [PATCH 176/297] Use sudo to add bin symlink in rpm Fixes #6338 --- resources/linux/rpm/code.spec.template | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/linux/rpm/code.spec.template b/resources/linux/rpm/code.spec.template index 33470043be6..0c93bc83170 100644 --- a/resources/linux/rpm/code.spec.template +++ b/resources/linux/rpm/code.spec.template @@ -28,9 +28,9 @@ if [ "@@NAME@@" = "code" ]; then rm -f /usr/local/bin/code fi -# Symlink bin command to /usr/bin2 +# Symlink bin command to /usr/bin rm -f /usr/bin/@@NAME@@ -ln -s /usr/share/@@NAME@@/bin/@@NAME@@ /usr/bin/@@NAME@@ +sudo ln -s /usr/share/@@NAME@@/bin/@@NAME@@ /usr/bin/@@NAME@@ # Register yum repository # TODO: #229: Enable once the yum repository is signed From 0b37d2acb9ff752bc783598ce9ff8dc357eeb66b Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 13 May 2016 15:14:28 -0700 Subject: [PATCH 177/297] Have rpm remove bin symlink in post uninstall step Related #6338 --- resources/linux/rpm/code.spec.template | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/resources/linux/rpm/code.spec.template b/resources/linux/rpm/code.spec.template index 0c93bc83170..65bc8dfbf16 100644 --- a/resources/linux/rpm/code.spec.template +++ b/resources/linux/rpm/code.spec.template @@ -29,7 +29,7 @@ if [ "@@NAME@@" = "code" ]; then fi # Symlink bin command to /usr/bin -rm -f /usr/bin/@@NAME@@ +sudo rm -f /usr/bin/@@NAME@@ sudo ln -s /usr/share/@@NAME@@/bin/@@NAME@@ /usr/bin/@@NAME@@ # Register yum repository @@ -42,6 +42,9 @@ sudo ln -s /usr/share/@@NAME@@/bin/@@NAME@@ /usr/bin/@@NAME@@ # fi #fi +%postun +sudo rm -f /usr/bin/@@NAME@@ + %files %defattr(-,root,root) From d96e0df5ba9e788ad1dd3b9e546aa66b5070a1f5 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 13 May 2016 15:28:28 -0700 Subject: [PATCH 178/297] Remove bin command in post install step for deb --- build/gulpfile.vscode.js | 6 +++++- resources/linux/debian/postrm.template | 6 ++++++ 2 files changed, 11 insertions(+), 1 deletion(-) create mode 100755 resources/linux/debian/postrm.template diff --git a/build/gulpfile.vscode.js b/build/gulpfile.vscode.js index 532a059f5e4..2be526d67a4 100644 --- a/build/gulpfile.vscode.js +++ b/build/gulpfile.vscode.js @@ -296,6 +296,10 @@ function prepareDebPackage(arch) { .pipe(replace('@@NAME@@', product.applicationName)) .pipe(rename('DEBIAN/prerm')) + var postrm = gulp.src('resources/linux/debian/postrm.template', { base: '.' }) + .pipe(replace('@@NAME@@', product.applicationName)) + .pipe(rename('DEBIAN/postrm')) + var postinst = gulp.src('resources/linux/debian/postinst.template', { base: '.' }) .pipe(replace('@@NAME@@', product.applicationName)) .pipe(replace('@@ARCHITECTURE@@', debArch)) @@ -303,7 +307,7 @@ function prepareDebPackage(arch) { .pipe(replace('@@UPDATEURL@@', product.updateUrl || '@@UPDATEURL@@')) .pipe(rename('DEBIAN/postinst')) - var all = es.merge(control, postinst, prerm, desktop, icon, code); + var all = es.merge(control, postinst, postrm, prerm, desktop, icon, code); return all.pipe(symdest(destination)); }; diff --git a/resources/linux/debian/postrm.template b/resources/linux/debian/postrm.template new file mode 100755 index 00000000000..1dfa892a0ea --- /dev/null +++ b/resources/linux/debian/postrm.template @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +# +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. + +rm -f /usr/bin/@@NAME@@ \ No newline at end of file From 4d215d87a9dc3225a1dde9f75bb33a5190cf0ddc Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 13 May 2016 17:59:17 -0700 Subject: [PATCH 179/297] Improve Linux external terminal defaults Related #5780 --- .../parts/execution/electron-browser/terminal.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/parts/execution/electron-browser/terminal.ts b/src/vs/workbench/parts/execution/electron-browser/terminal.ts index 87b56b1c000..f8651232c0b 100644 --- a/src/vs/workbench/parts/execution/electron-browser/terminal.ts +++ b/src/vs/workbench/parts/execution/electron-browser/terminal.ts @@ -5,8 +5,16 @@ import fs = require('fs'); import env = require('vs/base/common/platform'); -// If the system is not debian but is on gnome, use gnome-terminal -export const DEFAULT_TERMINAL_LINUX = (env.isLinux && !fs.existsSync('/etc/debian_version') && process.env.DESKTOP_SESSION === 'gnome') ? 'gnome-terminal' : 'x-terminal-emulator'; +let defaultTerminalLinux = 'xterm'; +if (env.isLinux) { + if (fs.existsSync('/etc/debian_version')) { + defaultTerminalLinux = 'x-terminal-emulator'; + } else if (process.env.DESKTOP_SESSION === 'gnome' || process.env.DESKTOP_SESSION === 'gnome-classic') { + defaultTerminalLinux = 'gnome-terminal'; + } +} + +export const DEFAULT_TERMINAL_LINUX = defaultTerminalLinux; export const DEFAULT_TERMINAL_WINDOWS = 'cmd'; From a631525fbb1bc0798104ecf6fb54cbda56d1409d Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 13 May 2016 18:49:43 -0700 Subject: [PATCH 180/297] Have --install-extension exit earlier if already installed Fixes #6364 --- src/vs/code/node/cliProcessMain.ts | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/vs/code/node/cliProcessMain.ts b/src/vs/code/node/cliProcessMain.ts index c98f1167632..a25fc9012a2 100644 --- a/src/vs/code/node/cliProcessMain.ts +++ b/src/vs/code/node/cliProcessMain.ts @@ -59,19 +59,20 @@ class Main { } private installExtension(ids: string[]): TPromise { - return sequence(ids.map(id => () => { - return this.extensionGalleryService.query({ ids: [id] }).then(result => { - const [extension] = result.firstPage; + return this.extensionManagementService.getInstalled().then(installed => { + return sequence(ids.map(id => () => { - if (!extension) { - return TPromise.wrapError(`${ notFound(id) }\n${ useId }`); + const isInstalled = installed.some(e => getExtensionId(e) === id); + + if (isInstalled) { + return TPromise.wrapError(localize('alreadyInstalled', "Extension '{0}' is already installed.", id)); } - return this.extensionManagementService.getInstalled().then(installed => { - const isInstalled = installed.some(e => getExtensionId(e) === id); + return this.extensionGalleryService.query({ ids: [id] }).then(result => { + const [extension] = result.firstPage; - if (isInstalled) { - return TPromise.wrapError(localize('alreadyInstalled', "Extension '{0}' is already installed.", id)); + if (!extension) { + return TPromise.wrapError(`${ notFound(id) }\n${ useId }`); } console.log(localize('foundExtension', "Found '{0}' in the marketplace.", id)); @@ -81,8 +82,8 @@ class Main { console.log(localize('successInstall', "Extension '{0}' v{1} was successfully installed!", id, extension.version)); }); }); - }); - })); + })); + }); } private uninstallExtension(ids: string[]): TPromise { From 9cff38ac885b2baf833a6346ff5fa23ac32ae2c8 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 13 May 2016 19:07:14 -0700 Subject: [PATCH 181/297] Improve external terminal support on xfce Fixes #5780 --- src/vs/workbench/parts/execution/electron-browser/terminal.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/vs/workbench/parts/execution/electron-browser/terminal.ts b/src/vs/workbench/parts/execution/electron-browser/terminal.ts index f8651232c0b..5e7fe0e8a82 100644 --- a/src/vs/workbench/parts/execution/electron-browser/terminal.ts +++ b/src/vs/workbench/parts/execution/electron-browser/terminal.ts @@ -11,6 +11,10 @@ if (env.isLinux) { defaultTerminalLinux = 'x-terminal-emulator'; } else if (process.env.DESKTOP_SESSION === 'gnome' || process.env.DESKTOP_SESSION === 'gnome-classic') { defaultTerminalLinux = 'gnome-terminal'; + } else if (process.env.COLORTERM) { + defaultTerminalLinux = process.env.COLORTERM; + } else if (process.env.TERM) { + defaultTerminalLinux = process.env.TERM; } } From cd1d4d8f551ec3d025d60a89ee8eb1b7dff4641f Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 13 May 2016 19:35:42 -0700 Subject: [PATCH 182/297] Clearing WorkingFilesModel should only add file types to recently closed files Fixes #5997 --- .../parts/files/common/workingFilesModel.ts | 8 ++++---- .../files/test/browser/workingFilesModel.test.ts | 15 +++++++++++++++ 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/parts/files/common/workingFilesModel.ts b/src/vs/workbench/parts/files/common/workingFilesModel.ts index b981bb04fba..8bb487e736b 100644 --- a/src/vs/workbench/parts/files/common/workingFilesModel.ts +++ b/src/vs/workbench/parts/files/common/workingFilesModel.ts @@ -355,14 +355,14 @@ export class WorkingFilesModel implements IWorkingFilesModel { // Put the active entry on the top of the stack let input = this.editorService.getActiveEditorInput(); - let resource: uri = getUntitledOrFileResource(input); + let activeResource: uri = getUntitledOrFileResource(input); let activeEntry: WorkingFileEntry; - if (resource) { - activeEntry = this.findEntry(resource); + if (activeResource && activeResource.scheme === 'file') { + activeEntry = this.findEntry(activeResource); } this.recentlyClosedEntries = this.recentlyClosedEntries.concat(resources.filter(e => { - return !activeEntry || e.resource.path !== activeEntry.resource.path; + return (!activeEntry || e.resource.path !== activeEntry.resource.path) && e.resource.scheme === 'file'; })); if (activeEntry) { diff --git a/src/vs/workbench/parts/files/test/browser/workingFilesModel.test.ts b/src/vs/workbench/parts/files/test/browser/workingFilesModel.test.ts index e946926e65e..e43289f062e 100644 --- a/src/vs/workbench/parts/files/test/browser/workingFilesModel.test.ts +++ b/src/vs/workbench/parts/files/test/browser/workingFilesModel.test.ts @@ -116,6 +116,21 @@ suite('Files - WorkingFilesModel', () => { assert.equal(model.popLastClosedEntry(), null); }); + test("Clearing the model only adds files to the closed entries", function() { + let model = baseInstantiationService.createInstance(WorkingFilesModel); + + model.addEntry(URI.create('untitled', null, '/foo')); + assert.equal(model.popLastClosedEntry(), null); + model.clear(); + assert.equal(model.popLastClosedEntry(), null); + + model.addEntry(URI.create('file', null, '/foo')); + model.addEntry(URI.create('untitled', null, '/bar')); + model.clear(); + assert.ok(model.popLastClosedEntry().isFile); + assert.equal(model.popLastClosedEntry(), null); + }); + test("Reopening multiple files will open the editor in the previously opened file", function() { let model = baseInstantiationService.createInstance(WorkingFilesModel); From f2ff1361344bec4bfa08af359c4d5132b1d0772d Mon Sep 17 00:00:00 2001 From: J/A Date: Sat, 14 May 2016 23:03:47 -0500 Subject: [PATCH 183/297] Do not autoclose `'` `'` is used to denote a lifetime, as in `fn foo<'a>(bar: &'a Baz) { ...` and it isn't helpful to have it automatically closed. --- extensions/rust/rust.configuration.json | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/extensions/rust/rust.configuration.json b/extensions/rust/rust.configuration.json index e4656d0babb..34396c3121e 100644 --- a/extensions/rust/rust.configuration.json +++ b/extensions/rust/rust.configuration.json @@ -12,8 +12,7 @@ ["{", "}"], ["[", "]"], ["(", ")"], - ["\"", "\""], - ["'", "'"] + ["\"", "\""] ], "surroundingPairs": [ ["{", "}"], @@ -22,4 +21,4 @@ ["\"", "\""], ["'", "'"] ] -} \ No newline at end of file +} From 3c748fa1955ade5578df9a2f3dab922aa722ebc7 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Sun, 15 May 2016 21:03:21 +0200 Subject: [PATCH 184/297] html.ts: Typo in comment --- src/vs/languages/html/common/html.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/languages/html/common/html.ts b/src/vs/languages/html/common/html.ts index adbc95bf164..cb3679a0562 100644 --- a/src/vs/languages/html/common/html.ts +++ b/src/vs/languages/html/common/html.ts @@ -24,8 +24,8 @@ import {ParameterHintsSupport} from 'vs/editor/common/modes/supports/parameterHi import {SuggestSupport} from 'vs/editor/common/modes/supports/suggestSupport'; import {IThreadService} from 'vs/platform/thread/common/thread'; -export { htmlTokenTypes }; // export to be used by Razor. We are the main module, so Razor should get ot from use. -export { EMPTY_ELEMENTS }; // export to be used by Razor. We are the main module, so Razor should get ot from use. +export { htmlTokenTypes }; // export to be used by Razor. We are the main module, so Razor should get it from us. +export { EMPTY_ELEMENTS }; // export to be used by Razor. We are the main module, so Razor should get it from us. export enum States { Content, From 48e8164164c91f91e8085ac5305e1bb5acf23f26 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Sun, 15 May 2016 21:19:22 +0200 Subject: [PATCH 185/297] Update json.ts to latest jsonc-parser --- src/vs/base/common/json.ts | 536 ++++++++++++++---- src/vs/base/test/common/json.test.ts | 8 +- src/vs/editor/node/textMate/TMSnippets.ts | 6 +- .../json/common/jsonSchemaService.ts | 6 +- .../json/common/parser/jsonParser.ts | 2 +- src/vs/workbench/node/extensionPoints.ts | 8 +- .../themes/electron-browser/themeService.ts | 4 +- 7 files changed, 449 insertions(+), 121 deletions(-) diff --git a/src/vs/base/common/json.ts b/src/vs/base/common/json.ts index 6b578d2c8a9..fbec4a76493 100644 --- a/src/vs/base/common/json.ts +++ b/src/vs/base/common/json.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import nls = require('vs/nls'); +import {localize} from 'vs/nls'; export enum ScanError { None, @@ -35,19 +35,50 @@ export enum SyntaxKind { EOF } +/** + * The scanner object, representing a JSON scanner at a position in the input string. + */ export interface JSONScanner { + /** + * Sets the scan position to a new offset. A call to 'scan' is needed to get the first token. + */ + setPosition(pos: number); + /** + * Read the next token. Returns the tolen code. + */ scan(): SyntaxKind; + /** + * Returns the current scan position, which is after the last read token. + */ getPosition(): number; + /** + * Returns the last read token. + */ getToken(): SyntaxKind; + /** + * Returns the last read token value. The value for strings is the decoded string content. For numbers its of type number, for boolean it's true or false. + */ getTokenValue(): string; + /** + * The start offset of the last read token. + */ getTokenOffset(): number; + /** + * The length of the last read token. + */ getTokenLength(): number; + /** + * An error code of the last scan. + */ getTokenError(): ScanError; } - +/** + * Creates a JSON scanner on the given text. + * If ignoreTrivia is set, whitespaces or comments are ignored. + */ export function createScanner(text:string, ignoreTrivia:boolean = false):JSONScanner { - var pos = 0, + let pos = 0, len = text.length, value:string = '', tokenOffset = 0, @@ -55,10 +86,10 @@ export function createScanner(text:string, ignoreTrivia:boolean = false):JSONSca scanError:ScanError = ScanError.None; function scanHexDigits(count: number, exact?: boolean): number { - var digits = 0; - var value = 0; + let digits = 0; + let value = 0; while (digits < count || !exact) { - var ch = text.charCodeAt(pos); + let ch = text.charCodeAt(pos); if (ch >= CharacterCodes._0 && ch <= CharacterCodes._9) { value = value * 16 + ch - CharacterCodes._0; } @@ -80,8 +111,16 @@ export function createScanner(text:string, ignoreTrivia:boolean = false):JSONSca return value; } + function setPosition(newPosition: number) { + pos = newPosition; + value = ''; + tokenOffset = 0; + token = SyntaxKind.Unknown; + scanError = ScanError.None; + } + function scanNumber(): string { - var start = pos; + let start = pos; if (text.charCodeAt(pos) === CharacterCodes._0) { pos++; } else { @@ -99,10 +138,10 @@ export function createScanner(text:string, ignoreTrivia:boolean = false):JSONSca } } else { scanError = ScanError.UnexpectedEndOfNumber; - return text.substring(start, end); + return text.substring(start, pos); } } - var end = pos; + let end = pos; if (pos < text.length && (text.charCodeAt(pos) === CharacterCodes.E || text.charCodeAt(pos) === CharacterCodes.e)) { pos++; if (pos < text.length && text.charCodeAt(pos) === CharacterCodes.plus || text.charCodeAt(pos) === CharacterCodes.minus) { @@ -123,7 +162,7 @@ export function createScanner(text:string, ignoreTrivia:boolean = false):JSONSca function scanString(): string { - var result = '', + let result = '', start = pos; while (true) { @@ -132,7 +171,7 @@ export function createScanner(text:string, ignoreTrivia:boolean = false):JSONSca scanError = ScanError.UnexpectedEndOfString; break; } - var ch = text.charCodeAt(pos); + let ch = text.charCodeAt(pos); if (ch === CharacterCodes.doubleQuote) { result += text.substring(start, pos); pos++; @@ -172,7 +211,7 @@ export function createScanner(text:string, ignoreTrivia:boolean = false):JSONSca result += '\t'; break; case CharacterCodes.u: - var ch = scanHexDigits(4, true); + let ch = scanHexDigits(4, true); if (ch >= 0) { result += String.fromCharCode(ch); } else { @@ -208,7 +247,7 @@ export function createScanner(text:string, ignoreTrivia:boolean = false):JSONSca return token = SyntaxKind.EOF; } - var code = text.charCodeAt(pos); + let code = text.charCodeAt(pos); // trivia: whitespace if (isWhiteSpace(code)) { do { @@ -260,7 +299,7 @@ export function createScanner(text:string, ignoreTrivia:boolean = false):JSONSca // comments case CharacterCodes.slash: - var start = pos - 1; + let start = pos - 1; // Single-line comment if (text.charCodeAt(pos + 1) === CharacterCodes.slash) { pos += 2; @@ -280,10 +319,10 @@ export function createScanner(text:string, ignoreTrivia:boolean = false):JSONSca if (text.charCodeAt(pos + 1) === CharacterCodes.asterisk) { pos += 2; - var safeLength = len - 1; // For lookahead. - var commentClosed = false; + let safeLength = len - 1; // For lookahead. + let commentClosed = false; while (pos < safeLength) { - var ch = text.charCodeAt(pos); + let ch = text.charCodeAt(pos); if (ch === CharacterCodes.asterisk && text.charCodeAt(pos + 1) === CharacterCodes.slash) { pos += 2; @@ -371,7 +410,7 @@ export function createScanner(text:string, ignoreTrivia:boolean = false):JSONSca function scanNextNonTrivia():SyntaxKind { - var result : SyntaxKind; + let result : SyntaxKind; do { result = scanNext(); } while (result >= SyntaxKind.LineCommentTrivia && result <= SyntaxKind.Trivia); @@ -379,6 +418,7 @@ export function createScanner(text:string, ignoreTrivia:boolean = false):JSONSca } return { + setPosition: setPosition, getPosition: () => pos, scan: ignoreTrivia ? scanNextNonTrivia : scanNext, getToken: () => token, @@ -403,10 +443,6 @@ function isDigit(ch: number): boolean { return ch >= CharacterCodes._0 && ch <= CharacterCodes._9; } -export function isLetter(ch: number): boolean { - return ch >= CharacterCodes.a && ch <= CharacterCodes.z || ch >= CharacterCodes.A && ch <= CharacterCodes.Z; -} - enum CharacterCodes { nullCharacter = 0, maxAsciiCharacter = 0x7F, @@ -552,7 +588,7 @@ enum CharacterCodes { */ export function stripComments(text:string, replaceCh?:string):string { - var _scanner = createScanner(text), + let _scanner = createScanner(text), parts: string[] = [], kind:SyntaxKind, offset = 0, @@ -579,23 +615,285 @@ export function stripComments(text:string, replaceCh?:string):string { return parts.join(''); } -export function parse(text:string, errors: string[] = []) : any { - var noMatch = Object(); - var _scanner = createScanner(text, true); +export interface ParseError { + error: ParseErrorCode; +} - function scanNext() : SyntaxKind { - var token = _scanner.scan(); - while (token === SyntaxKind.Unknown) { - handleError(nls.localize('UnknownSymbol', 'Invalid symbol')); - token = _scanner.scan(); +export enum ParseErrorCode { + InvalidSymbol, + InvalidNumberFormat, + PropertyNameExpected, + ValueExpected, + ColonExpected, + CommaExpected, + CloseBraceExpected, + CloseBracketExpected, + EndOfFileExpected +} + +export function getParseErrorMessage(errorCode: ParseErrorCode) : string { + switch (errorCode) { + case ParseErrorCode.InvalidSymbol: return localize('error.invalidSymbol', 'Invalid symbol'); + case ParseErrorCode.InvalidNumberFormat: return localize('error.invalidNumberFormat', 'Invalid number format'); + case ParseErrorCode.PropertyNameExpected: return localize('error.propertyNameExpected', 'Property name expected'); + case ParseErrorCode.ValueExpected: return localize('error.valueExpected', 'Value expected'); + case ParseErrorCode.ColonExpected: return localize('error.colonExpected', 'Colon expected'); + case ParseErrorCode.CommaExpected: return localize('error.commaExpected', 'Comma expected'); + case ParseErrorCode.CloseBraceExpected: return localize('error.closeBraceExpected', 'Closing brace expected'); + case ParseErrorCode.CloseBracketExpected: return localize('error.closeBracketExpected', 'Closing bracket expected'); + case ParseErrorCode.EndOfFileExpected: return localize('error.endOfFileExpected', 'End of file expected'); + default: + return ''; + } +} + +export type NodeType = "object" | "array" | "property" | "string" | "number" | "null"; + +export interface Node { + type: NodeType; + value: any; + offset: number; + length: number; + columnOffset?: number; +} + +export interface Location { + previousNode?: Node; + segments: string[]; + matches: (segments: string[]) => boolean; + completeProperty: boolean; +} + + +/** + * For a given offset, evaluate the location in the JSON document. Each segment in a location is either a property names or an array accessors. + */ +export function getLocation(text:string, position: number) : Location { + let segments: string[] = []; + let earlyReturnException = new Object(); + let previousNode : Node = void 0; + const previousNodeInst : Node = { + value: void 0, + offset: void 0, + length: void 0, + type: void 0 + }; + let completeProperty = false; + let hasComma = false; + function setPreviousNode(value: string, offset: number, length: number, type: NodeType) { + previousNodeInst.value = value; + previousNodeInst.offset = offset; + previousNodeInst.length = length; + previousNodeInst.type = type; + previousNodeInst.columnOffset = void 0; + previousNode = previousNodeInst; + } + try { + + visit(text, { + onObjectBegin: (offset: number, length: number) => { + if (position <= offset) { + throw earlyReturnException; + } + previousNode = void 0; + completeProperty = position > offset; + hasComma = false; + }, + onObjectProperty: (name: string, offset: number, length: number) => { + if (position < offset) { + throw earlyReturnException; + } + setPreviousNode(name, offset, length, 'property'); + hasComma = false; + segments.push(name); + if (position <= offset + length) { + throw earlyReturnException; + } + }, + onObjectEnd: (offset: number, length: number) => { + if (position <= offset) { + throw earlyReturnException; + } + previousNode = void 0; + if (!hasComma) { + segments.pop(); + } + hasComma = false; + }, + onArrayBegin: (offset: number, length: number) => { + if (position <= offset) { + throw earlyReturnException; + } + previousNode = void 0; + segments.push('[0]'); + hasComma = false; + }, + onArrayEnd: (offset: number, length: number) => { + if (position <= offset) { + throw earlyReturnException; + } + previousNode = void 0; + if (!hasComma) { + segments.pop(); + } + hasComma = false; + }, + onLiteralValue: (value: any, offset: number, length: number) => { + if (position < offset) { + throw earlyReturnException; + } + setPreviousNode(value, offset, length, value === null ? 'null' : (typeof value === 'string' ? 'string' : 'number')); + if (position <= offset + length) { + throw earlyReturnException; + } + }, + onSeparator: (sep: string, offset: number, length: number) => { + if (position <= offset) { + throw earlyReturnException; + } + if (sep === ':' && previousNode.type === 'property') { + previousNode.columnOffset = offset; + completeProperty = false; + previousNode = void 0; + } else if (sep === ',') { + let last = segments.pop(); + if (last[0] === '[' && last[last.length - 1] === ']') { + segments.push('[' + (parseInt(last.substr(1, last.length - 2)) + 1) + ']'); + } else { + completeProperty = true; + } + previousNode = void 0; + hasComma = true; + } + } + }); + } catch (e) { + if (e !== earlyReturnException) { + throw e; + } + } + return { + segments, + previousNode, + completeProperty, + matches: (pattern: string[]) => { + let k = 0; + for (let i = 0; k < pattern.length && i < segments.length; i++) { + if (pattern[k] === segments[i] || pattern[k] === '*') { + k++; + } else if (pattern[k] !== '**') { + return false; + } + } + return k === pattern.length; + } + }; +} + +export interface ParseOptions { + disallowComments?: boolean; +} + +/** + * Parses the given text and returns the object the JSON content represents. On invalid input, the parser tries to be as fault lolerant as possible, but still return a result. + * Therefore always check the errors list to find out if the input was valid. + */ +export function parse(text:string, errors: ParseError[] = [], options?: ParseOptions) : any { + let currentProperty : string = null; + let currentParent : any = []; + let previousParents : any[] = []; + + function onValue(value: any) { + if (Array.isArray(currentParent)) { + ( currentParent).push(value); + } else if (currentProperty) { + currentParent[currentProperty] = value; } - return token; } - function handleError(message:string, skipUntilAfter: SyntaxKind[] = [], skipUntil: SyntaxKind[] = []) : void { - errors.push(message); + let visitor = { + onObjectBegin: () => { + let object = {}; + onValue(object); + previousParents.push(currentParent); + currentParent = object; + currentProperty = null; + }, + onObjectProperty: (name: string) => { + currentProperty = name; + }, + onObjectEnd: () => { + currentParent = previousParents.pop(); + }, + onArrayBegin: () => { + let array = []; + onValue(array); + previousParents.push(currentParent); + currentParent = array; + currentProperty = null; + }, + onArrayEnd: () => { + currentParent = previousParents.pop(); + }, + onLiteralValue: onValue, + onError:(error:ParseErrorCode) => { + errors.push({error: error}); + } + }; + visit(text, visitor, options); + return currentParent[0]; +} + +/** + * Parses the given text and invokes the visitor functions for each object, array and literal reached. + */ +export function visit(text:string, visitor: JSONVisitor, options?: ParseOptions) : any { + + let _scanner = createScanner(text, false); + + function toNoArgVisit(visitFunction: (offset: number, length: number) => void) : () => void { + return visitFunction ? () => visitFunction(_scanner.getTokenOffset(), _scanner.getTokenLength()) : () => true; + } + function toOneArgVisit(visitFunction: (arg: T, offset: number, length: number) => void) : (arg: T) => void { + return visitFunction ? (arg: T) => visitFunction(arg, _scanner.getTokenOffset(), _scanner.getTokenLength()) : () => true; + } + + let onObjectBegin = toNoArgVisit(visitor.onObjectBegin), + onObjectProperty = toOneArgVisit(visitor.onObjectProperty), + onObjectEnd = toNoArgVisit(visitor.onObjectEnd), + onArrayBegin = toNoArgVisit(visitor.onArrayBegin), + onArrayEnd = toNoArgVisit(visitor.onArrayEnd), + onLiteralValue = toOneArgVisit(visitor.onLiteralValue), + onSeparator = toOneArgVisit(visitor.onSeparator), + onError = toOneArgVisit(visitor.onError); + + let disallowComments = options && options.disallowComments; + function scanNext() : SyntaxKind { + while (true) { + let token = _scanner.scan(); + switch (token) { + case SyntaxKind.LineCommentTrivia: + case SyntaxKind.BlockCommentTrivia: + if (disallowComments) { + handleError(ParseErrorCode.InvalidSymbol); + } + break; + case SyntaxKind.Unknown: + handleError(ParseErrorCode.InvalidSymbol); + break; + case SyntaxKind.Trivia: + case SyntaxKind.LineBreakTrivia: + break; + default: + return token; + } + } + } + + function handleError(error:ParseErrorCode, skipUntilAfter: SyntaxKind[] = [], skipUntil: SyntaxKind[] = []) : void { + onError(error); if (skipUntilAfter.length + skipUntil.length > 0) { - var token = _scanner.getToken(); + let token = _scanner.getToken(); while (token !== SyntaxKind.EOF) { if (skipUntilAfter.indexOf(token) !== -1) { scanNext(); @@ -608,156 +906,186 @@ export function parse(text:string, errors: string[] = []) : any { } } - function parseString() : any { + function parseString(isValue: boolean) : boolean { if (_scanner.getToken() !== SyntaxKind.StringLiteral) { - return noMatch; + return false; + } + let value = _scanner.getTokenValue(); + if (isValue) { + onLiteralValue(value); + } else { + onObjectProperty(value); } - var value = _scanner.getTokenValue(); scanNext(); - return value; + return true; } - function parseLiteral() : any { - var value : any; + function parseLiteral() : boolean { switch (_scanner.getToken()) { case SyntaxKind.NumericLiteral: + let value = 0; try { value = JSON.parse(_scanner.getTokenValue()); if (typeof value !== 'number') { - handleError(nls.localize('InvalidNumberFormat', 'Invalid number format')); + handleError(ParseErrorCode.InvalidNumberFormat); value = 0; } } catch (e) { - value = 0; + handleError(ParseErrorCode.InvalidNumberFormat); } + onLiteralValue(value); break; case SyntaxKind.NullKeyword: - value = null; + onLiteralValue(null); break; case SyntaxKind.TrueKeyword: - value = true; + onLiteralValue(true); break; case SyntaxKind.FalseKeyword: - value = false; + onLiteralValue(false); break; default: - return noMatch; + return false; } scanNext(); - return value; + return true; } - function parseProperty(result: any) : any { - var key = parseString(); - if (key === noMatch) { - handleError(nls.localize('PropertyExpected', 'Property name expected'), [], [SyntaxKind.CloseBraceToken, SyntaxKind.CommaToken] ); + function parseProperty() : boolean { + if (!parseString(false)) { + handleError(ParseErrorCode.PropertyNameExpected, [], [SyntaxKind.CloseBraceToken, SyntaxKind.CommaToken] ); return false; } if (_scanner.getToken() === SyntaxKind.ColonToken) { + onSeparator(':'); scanNext(); // consume colon - var value = parseValue(); - if (value !== noMatch) { - result[key] = value; - } else { - handleError(nls.localize('ValueExpected', 'Value expected'), [], [SyntaxKind.CloseBraceToken, SyntaxKind.CommaToken] ); + if (!parseValue()) { + handleError(ParseErrorCode.ValueExpected, [], [SyntaxKind.CloseBraceToken, SyntaxKind.CommaToken] ); } } else { - handleError(nls.localize('ColonExpected', 'Colon expected'), [], [SyntaxKind.CloseBraceToken, SyntaxKind.CommaToken] ); + handleError(ParseErrorCode.ColonExpected, [], [SyntaxKind.CloseBraceToken, SyntaxKind.CommaToken] ); } return true; } - function parseObject() : any { + function parseObject() : boolean { if (_scanner.getToken() !== SyntaxKind.OpenBraceToken) { - return noMatch; + return false; } - var obj = {}; + onObjectBegin(); scanNext(); // consume open brace - var needsComma = false; + let needsComma = false; while (_scanner.getToken() !== SyntaxKind.CloseBraceToken && _scanner.getToken() !== SyntaxKind.EOF) { if (_scanner.getToken() === SyntaxKind.CommaToken) { if (!needsComma) { - handleError(nls.localize('ValueExpected', 'Value expected'), [], [] ); + handleError(ParseErrorCode.ValueExpected, [], [] ); } + onSeparator(','); scanNext(); // consume comma } else if (needsComma) { - handleError(nls.localize('CommaExpected', 'Comma expected'), [], [] ); + handleError(ParseErrorCode.CommaExpected, [], [] ); } - var propertyParsed = parseProperty(obj); - if (!propertyParsed) { - handleError(nls.localize('ValueExpected', 'Value expected'), [], [SyntaxKind.CloseBraceToken, SyntaxKind.CommaToken] ); + if (!parseProperty()) { + handleError(ParseErrorCode.ValueExpected, [], [SyntaxKind.CloseBraceToken, SyntaxKind.CommaToken] ); } needsComma = true; } - + onObjectEnd(); if (_scanner.getToken() !== SyntaxKind.CloseBraceToken) { - handleError(nls.localize('CloseBraceExpected', 'Closing brace expected'), [SyntaxKind.CloseBraceToken], []); + handleError(ParseErrorCode.CloseBraceExpected, [SyntaxKind.CloseBraceToken], []); } else { scanNext(); // consume close brace } - return obj; + return true; } - function parseArray() : any { + function parseArray() : boolean { if (_scanner.getToken() !== SyntaxKind.OpenBracketToken) { - return noMatch; + return false; } - var arr: any[] = []; + onArrayBegin(); scanNext(); // consume open bracket - var needsComma = false; + let needsComma = false; while (_scanner.getToken() !== SyntaxKind.CloseBracketToken && _scanner.getToken() !== SyntaxKind.EOF) { if (_scanner.getToken() === SyntaxKind.CommaToken) { if (!needsComma) { - handleError(nls.localize('ValeExpected', 'Value expected'), [], [] ); + handleError(ParseErrorCode.ValueExpected, [], [] ); } + onSeparator(','); scanNext(); // consume comma } else if (needsComma) { - handleError(nls.localize('CommaExpected', 'Comma expected'), [], [] ); + handleError(ParseErrorCode.CommaExpected, [], [] ); } - var value = parseValue(); - if (value === noMatch) { - handleError(nls.localize('ValueExpected', 'Value expected'), [], [SyntaxKind.CloseBracketToken, SyntaxKind.CommaToken] ); - } else { - arr.push(value); + if (!parseValue()) { + handleError(ParseErrorCode.ValueExpected, [], [SyntaxKind.CloseBracketToken, SyntaxKind.CommaToken] ); } needsComma = true; } - + onArrayEnd(); if (_scanner.getToken() !== SyntaxKind.CloseBracketToken) { - handleError(nls.localize('CloseBracketExpected', 'Closing bracket expected'), [SyntaxKind.CloseBracketToken], []); + handleError(ParseErrorCode.CloseBracketExpected, [SyntaxKind.CloseBracketToken], []); } else { scanNext(); // consume close bracket } - return arr; + return true; } - function parseValue() : any { - var result = parseArray(); - if (result !== noMatch) { - return result; - } - result = parseObject(); - if (result !== noMatch) { - return result; - } - result = parseString(); - if (result !== noMatch) { - return result; - } - return parseLiteral(); + function parseValue() : boolean { + return parseArray() || parseObject() || parseString(true) || parseLiteral(); } scanNext(); - var value = parseValue(); - if (value === noMatch) { - handleError(nls.localize('ValueExpected', 'Value expected'), [], []); - return void 0; + if (!parseValue()) { + handleError(ParseErrorCode.ValueExpected, [], []); + return false; } if (_scanner.getToken() !== SyntaxKind.EOF) { - handleError(nls.localize('EOFExpected', 'End of content expected'), [], []); + handleError(ParseErrorCode.EndOfFileExpected, [], []); } - return value; + return true; } + +export interface JSONVisitor { + /** + * Invoked when an open brace is encountered and an object is started. The offset and length represent the location of the open brace. + */ + onObjectBegin?: (offset:number, length:number) => void; + + /** + * Invoked when a property is encountered. The offset and length represent the location of the property name. + */ + onObjectProperty?: (property: string, offset:number, length:number) => void; + + /** + * Invoked when a closing brace is encountered and an object is completed. The offset and length represent the location of the closing brace. + */ + onObjectEnd?: (offset:number, length:number) => void; + + /** + * Invoked when an open bracket is encountered. The offset and length represent the location of the open bracket. + */ + onArrayBegin?: (offset:number, length:number) => void; + + /** + * Invoked when a closing bracket is encountered. The offset and length represent the location of the closing bracket. + */ + onArrayEnd?: (offset:number, length:number) => void; + + /** + * Invoked when a literal value is encountered. The offset and length represent the location of the literal value. + */ + onLiteralValue?: (value: any, offset:number, length:number) => void; + + /** + * Invoked when a comma or colon separator is encountered. The offset and length represent the location of the separator. + */ + onSeparator?: (charcter: string, offset:number, length:number) => void; + + /** + * Invoked on an error. + */ + onError?: (error: ParseErrorCode, offset:number, length:number) => void; +} \ No newline at end of file diff --git a/src/vs/base/test/common/json.test.ts b/src/vs/base/test/common/json.test.ts index d0dd7e06a46..74f4211419c 100644 --- a/src/vs/base/test/common/json.test.ts +++ b/src/vs/base/test/common/json.test.ts @@ -5,7 +5,7 @@ 'use strict'; import * as assert from 'assert'; -import { SyntaxKind, createScanner, parse } from 'vs/base/common/json'; +import { SyntaxKind, createScanner, parse, ParseError, getParseErrorMessage } from 'vs/base/common/json'; function assertKinds(text:string, ...kinds:SyntaxKind[]):void { var _json = createScanner(text); @@ -18,17 +18,17 @@ function assertKinds(text:string, ...kinds:SyntaxKind[]):void { function assertValidParse(input:string, expected:any) : void { - var errors : string[] = []; + var errors : ParseError[] = []; var actual = parse(input, errors); if (errors.length !== 0) { - assert(false, errors[0]); + assert(false, getParseErrorMessage(errors[0].error)); } assert.deepEqual(actual, expected); } function assertInvalidParse(input:string, expected:any) : void { - var errors : string[] = []; + var errors : ParseError[] = []; var actual = parse(input, errors); assert(errors.length > 0); diff --git a/src/vs/editor/node/textMate/TMSnippets.ts b/src/vs/editor/node/textMate/TMSnippets.ts index d7ddd45d9d9..bef5e357c19 100644 --- a/src/vs/editor/node/textMate/TMSnippets.ts +++ b/src/vs/editor/node/textMate/TMSnippets.ts @@ -5,7 +5,7 @@ 'use strict'; import * as nls from 'vs/nls'; -import {parse} from 'vs/base/common/json'; +import {parse, ParseError} from 'vs/base/common/json'; import * as paths from 'vs/base/common/paths'; import {TPromise} from 'vs/base/common/winjs.base'; import {readFile} from 'vs/base/node/pfs'; @@ -23,7 +23,7 @@ export interface ITMSnippetsExtensionPoint { export function snippetUpdated(modeId: string, filePath: string): TPromise { return readFile(filePath).then((fileContents) => { - var errors: string[] = []; + var errors: ParseError[] = []; var snippetsObj = parse(fileContents.toString(), errors); var adaptedSnippets = TMSnippetsAdaptor.adapt(snippetsObj); SnippetsRegistry.registerSnippets(modeId, filePath, adaptedSnippets); @@ -98,7 +98,7 @@ export class MainProcessTextMateSnippet { public registerDefinition(modeId: string, filePath: string): void { readFile(filePath).then((fileContents) => { - var errors: string[] = []; + var errors: ParseError[] = []; var snippetsObj = parse(fileContents.toString(), errors); var adaptedSnippets = TMSnippetsAdaptor.adapt(snippetsObj); SnippetsRegistry.registerDefaultSnippets(modeId, adaptedSnippets); diff --git a/src/vs/languages/json/common/jsonSchemaService.ts b/src/vs/languages/json/common/jsonSchemaService.ts index e63e19bd27c..582f7066ddd 100644 --- a/src/vs/languages/json/common/jsonSchemaService.ts +++ b/src/vs/languages/json/common/jsonSchemaService.ts @@ -342,9 +342,9 @@ export class JSONSchemaService implements IJSONSchemaService { } var schemaContent: IJSONSchema = {}; - var jsonErrors = []; - schemaContent = Json.parse(content, errors); - var errors = jsonErrors.length ? [ nls.localize('json.schema.invalidFormat', 'Unable to parse content from \'{0}\': {1}.', toDisplayString(url), jsonErrors[0])] : []; + var jsonErrors: Json.ParseError[] = []; + schemaContent = Json.parse(content, jsonErrors); + var errors = jsonErrors.length ? [ nls.localize('json.schema.invalidFormat', 'Unable to parse content from \'{0}\': {1}.', toDisplayString(url), Json.getParseErrorMessage(jsonErrors[0].error))] : []; return new UnresolvedSchema(schemaContent, errors); }, (error : http.IXHRResponse) => { diff --git a/src/vs/languages/json/common/parser/jsonParser.ts b/src/vs/languages/json/common/parser/jsonParser.ts index df73072da3b..36f7ebce115 100644 --- a/src/vs/languages/json/common/parser/jsonParser.ts +++ b/src/vs/languages/json/common/parser/jsonParser.ts @@ -898,7 +898,7 @@ export class JSONParser { if (_scanner.getToken() === Json.SyntaxKind.Unknown) { // give a more helpful error message var value = _scanner.getTokenValue(); - if (value.length > 0 && (value.charAt(0) === '\'' || Json.isLetter(value.charAt(0).charCodeAt(0)))) { + if (value.match(/^['\w]/)) { _error(nls.localize('DoubleQuotesExpected', 'Property keys must be doublequoted')); } } diff --git a/src/vs/workbench/node/extensionPoints.ts b/src/vs/workbench/node/extensionPoints.ts index f99043133a4..94d46ceb446 100644 --- a/src/vs/workbench/node/extensionPoints.ts +++ b/src/vs/workbench/node/extensionPoints.ts @@ -83,11 +83,11 @@ abstract class ExtensionManifestHandler { class ExtensionManifestParser extends ExtensionManifestHandler { public parse(): TPromise { return pfs.readFile(this._absoluteManifestPath).then((manifestContents) => { - let errors: string[] = []; + let errors: json.ParseError[] = []; let extensionDescription: IExtensionDescription = json.parse(manifestContents.toString(), errors); if (errors.length > 0) { errors.forEach((error) => { - this._collector.error(this._absoluteFolderPath, nls.localize('jsonParseFail', "Failed to parse {0}: {1}.", this._absoluteManifestPath, error)); + this._collector.error(this._absoluteFolderPath, nls.localize('jsonParseFail', "Failed to parse {0}: {1}.", this._absoluteManifestPath, json.getParseErrorMessage(error.error))); }); return null; } @@ -114,11 +114,11 @@ class ExtensionManifestNLSReplacer extends ExtensionManifestHandler { return extensionDescription; } return pfs.readFile(messageBundle).then(messageBundleContent => { - let errors: string[] = []; + let errors: json.ParseError[] = []; let messages: { [key: string]: string; } = json.parse(messageBundleContent.toString(), errors); if (errors.length > 0) { errors.forEach((error) => { - this._collector.error(this._absoluteFolderPath, nls.localize('jsonParseFail', "Failed to parse {0}: {1}.", messageBundle, error)); + this._collector.error(this._absoluteFolderPath, nls.localize('jsonParseFail', "Failed to parse {0}: {1}.", messageBundle, json.getParseErrorMessage(error.error))); }); return extensionDescription; } diff --git a/src/vs/workbench/services/themes/electron-browser/themeService.ts b/src/vs/workbench/services/themes/electron-browser/themeService.ts index 3ca2cb6e367..066593f0b65 100644 --- a/src/vs/workbench/services/themes/electron-browser/themeService.ts +++ b/src/vs/workbench/services/themes/electron-browser/themeService.ts @@ -262,10 +262,10 @@ function applyTheme(theme: IThemeData, onApply: (themeId:string) => void): TProm function _loadThemeDocument(themePath: string) : TPromise { return pfs.readFile(themePath).then(content => { if (Paths.extname(themePath) === '.json') { - let errors: string[] = []; + let errors: Json.ParseError[] = []; let contentValue = Json.parse(content.toString(), errors); if (errors.length > 0) { - return TPromise.wrapError(new Error(nls.localize('error.cannotparsejson', "Problems parsing JSON theme file: {0}", errors.join(', ')))); + return TPromise.wrapError(new Error(nls.localize('error.cannotparsejson', "Problems parsing JSON theme file: {0}", errors.map(e => Json.getParseErrorMessage(e.error)).join(', ')))); } if (contentValue.include) { return _loadThemeDocument(Paths.join(Paths.dirname(themePath), contentValue.include)).then(includedValue => { From 1b31ce6babd7f20462d4c2047bd5fe6d64456687 Mon Sep 17 00:00:00 2001 From: rebornix Date: Sun, 15 May 2016 14:24:38 -0700 Subject: [PATCH 186/297] add touch screen tap support for reference search --- .../referenceSearch/browser/referencesWidget.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/vs/editor/contrib/referenceSearch/browser/referencesWidget.ts b/src/vs/editor/contrib/referenceSearch/browser/referencesWidget.ts index d184968b0c6..143176d21d6 100644 --- a/src/vs/editor/contrib/referenceSearch/browser/referencesWidget.ts +++ b/src/vs/editor/contrib/referenceSearch/browser/referencesWidget.ts @@ -19,6 +19,7 @@ import * as dom from 'vs/base/browser/dom'; import {Sash, ISashEvent, IVerticalSashLayoutProvider} from 'vs/base/browser/ui/sash/sash'; import {IKeyboardEvent} from 'vs/base/browser/keyboardEvent'; import {IMouseEvent} from 'vs/base/browser/mouseEvent'; +import {GestureEvent} from 'vs/base/browser/touch'; import {CountBadge} from 'vs/base/browser/ui/countBadge/countBadge'; import {FileLabel} from 'vs/base/browser/ui/filelabel/fileLabel'; import {LeftRightWidget} from 'vs/base/browser/ui/leftRightWidget/leftRightWidget'; @@ -212,6 +213,18 @@ class Controller extends DefaultController { OPEN_TO_SIDE: 'events/custom/opentoside' }; + public onTap(tree: tree.ITree, element: any, event: GestureEvent):boolean { + if (element instanceof FileReferences) { + event.preventDefault(); + event.stopPropagation(); + return this._expandCollapse(tree, element); + } + + var result = super.onTap(tree, element, event); + tree.emit(Controller.Events.FOCUSED, element); + return result; + } + public onMouseDown(tree:tree.ITree, element:any, event:IMouseEvent):boolean { if (event.leftButton) { if (element instanceof FileReferences) { From 323dec0c511fa76cf0849cf7585096e86c3ef1b0 Mon Sep 17 00:00:00 2001 From: isidor Date: Mon, 16 May 2016 10:08:14 +0200 Subject: [PATCH 187/297] debug: reveal auto expanded element in repl fixes #6343 --- src/vs/workbench/parts/debug/browser/repl.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/parts/debug/browser/repl.ts b/src/vs/workbench/parts/debug/browser/repl.ts index 5c860f6fb68..c19d92a1239 100644 --- a/src/vs/workbench/parts/debug/browser/repl.ts +++ b/src/vs/workbench/parts/debug/browser/repl.ts @@ -106,7 +106,9 @@ export class Repl extends Panel { const elements = this.debugService.getModel().getReplElements(); const lastElement = elements.length > 0 ? elements[elements.length - 1] : null; if (lastElement instanceof Expression && lastElement.reference > 0) { - return this.tree.expand(elements[elements.length - 1]); + return this.tree.expand(elements[elements.length - 1]).then(() => + this.tree.reveal(elements[elements.length - 1], 0) + ); } }, errors.onUnexpectedError); }, Repl.REFRESH_DELAY); From 60fe78cfa981f271c1930b4fbc0b4fdd91bdf8a2 Mon Sep 17 00:00:00 2001 From: isidor Date: Mon, 16 May 2016 10:21:31 +0200 Subject: [PATCH 188/297] fixes #6297 --- src/vs/workbench/parts/debug/browser/debugActionItems.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/parts/debug/browser/debugActionItems.ts b/src/vs/workbench/parts/debug/browser/debugActionItems.ts index ae050357f6f..578dfc3dd1d 100644 --- a/src/vs/workbench/parts/debug/browser/debugActionItems.ts +++ b/src/vs/workbench/parts/debug/browser/debugActionItems.ts @@ -73,7 +73,7 @@ export class SelectConfigActionItem extends BaseActionItem { if (!config || !config.configurations) { this.select.add(this.createOption(nls.localize('noConfigurations', "No Configurations"))); this.select.disabled = true; - return this.actionRunner.run(this._action, null); + return changeDebugConfiguration ? this.actionRunner.run(this._action, null) : null; } const configurations = config.configurations; From d1236f740f68a6de99523edcf94b8c182ee5e6d8 Mon Sep 17 00:00:00 2001 From: isidor Date: Mon, 16 May 2016 12:07:22 +0200 Subject: [PATCH 189/297] debug: do not trim whitespace in repl fixes #6275 --- src/vs/workbench/parts/debug/browser/media/repl.css | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/parts/debug/browser/media/repl.css b/src/vs/workbench/parts/debug/browser/media/repl.css index 800158210ff..4c751078d84 100644 --- a/src/vs/workbench/parts/debug/browser/media/repl.css +++ b/src/vs/workbench/parts/debug/browser/media/repl.css @@ -27,9 +27,10 @@ .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content { line-height: 18px; - word-wrap: break-word; - white-space: initial; -webkit-user-select: text; + /* Wrap words but also do not trim whitespace #6275 */ + word-wrap: break-word; + white-space: pre-wrap; } .monaco-workbench .repl .repl-tree .monaco-tree-row .input.expression.mac, From 8a3a8d0f676ee4a4f11113f8f85b94962736275b Mon Sep 17 00:00:00 2001 From: isidor Date: Mon, 16 May 2016 14:41:11 +0200 Subject: [PATCH 190/297] debug: move show more stack frames logic to call stack controller fixes #6299 --- .../parts/debug/browser/debugViewer.ts | 32 +++++++++++++++++++ .../parts/debug/browser/debugViews.ts | 15 +-------- 2 files changed, 33 insertions(+), 14 deletions(-) diff --git a/src/vs/workbench/parts/debug/browser/debugViewer.ts b/src/vs/workbench/parts/debug/browser/debugViewer.ts index 087e70fcbbc..1a1d5b87dea 100644 --- a/src/vs/workbench/parts/debug/browser/debugViewer.ts +++ b/src/vs/workbench/parts/debug/browser/debugViewer.ts @@ -193,6 +193,38 @@ export class BaseDebugController extends treedefaults.DefaultController { // call stack +export class CallStackController extends BaseDebugController { + + protected onLeftClick(tree: tree.ITree, element: any, event: mouse.IMouseEvent): boolean { + if (typeof element === 'number') { + return this.showMoreStackFrames(tree, element); + } + + return super.onLeftClick(tree, element, event); + } + + protected onEnter(tree: tree.ITree, event: IKeyboardEvent): boolean { + const element = tree.getFocus(); + if (typeof element === 'number') { + return this.showMoreStackFrames(tree, element); + } + + return super.onEnter(tree, event); + } + + // user clicked / pressed on 'Load More Stack Frames', get those stack frames and refresh the tree. + private showMoreStackFrames(tree: tree.ITree, threadId: number): boolean { + const thread = this.debugService.getModel().getThreads()[threadId]; + if (thread) { + thread.getCallStack(this.debugService, true) + .done(() => tree.refresh(), errors.onUnexpectedError); + } + + return true; + } +} + + export class CallStackActionProvider implements renderer.IActionProvider { constructor( @IInstantiationService private instantiationService: IInstantiationService) { diff --git a/src/vs/workbench/parts/debug/browser/debugViews.ts b/src/vs/workbench/parts/debug/browser/debugViews.ts index f86536cfb6c..30d85f69867 100644 --- a/src/vs/workbench/parts/debug/browser/debugViews.ts +++ b/src/vs/workbench/parts/debug/browser/debugViews.ts @@ -224,7 +224,7 @@ export class CallStackView extends viewlet.CollapsibleViewletView { dataSource: this.instantiationService.createInstance(viewer.CallStackDataSource), renderer: this.instantiationService.createInstance(viewer.CallStackRenderer), accessibilityProvider: this.instantiationService.createInstance(viewer.CallstackAccessibilityProvider), - controller: new viewer.BaseDebugController(this.debugService, this.contextMenuService, actionProvider) + controller: new viewer.CallStackController(this.debugService, this.contextMenuService, actionProvider) }, debugTreeOptions(nls.localize({ comment: ['Debug is a noun in this context, not a verb.'], key: 'callStackAriaLabel'}, "Debug Call Stack"))); this.toDispose.push(this.tree.addListener2('selection', (e: tree.ISelectionEvent) => { @@ -251,19 +251,6 @@ export class CallStackView extends viewlet.CollapsibleViewletView { const sideBySide = (originalEvent && (originalEvent.ctrlKey || originalEvent.metaKey)); this.debugService.openOrRevealSource(stackFrame.source, stackFrame.lineNumber, preserveFocus, sideBySide).done(null, errors.onUnexpectedError); } - - // user clicked on 'Load More Stack Frames', get those stack frames and refresh the tree. - if (typeof element === 'number') { - const thread = this.debugService.getModel().getThreads()[element]; - if (thread) { - thread.getCallStack(this.debugService, true) - .then(() => this.tree.refresh()) - .then(() => { - this.tree.clearFocus(); - this.tree.clearSelection(); - }).done(null, errors.onUnexpectedError); - } - } })); this.toDispose.push(this.tree.addListener2(events.EventType.FOCUS, (e: tree.IFocusEvent) => { From 8877119bd62fb4d4211e88cf78b1bd88f6adbe38 Mon Sep 17 00:00:00 2001 From: isidor Date: Mon, 16 May 2016 14:56:30 +0200 Subject: [PATCH 191/297] debug: move more logic to call stack controller --- .../parts/debug/browser/debugViewer.ts | 21 ++++++++++++--- .../parts/debug/browser/debugViews.ts | 26 ------------------- 2 files changed, 17 insertions(+), 30 deletions(-) diff --git a/src/vs/workbench/parts/debug/browser/debugViewer.ts b/src/vs/workbench/parts/debug/browser/debugViewer.ts index 1a1d5b87dea..f6c5abf9726 100644 --- a/src/vs/workbench/parts/debug/browser/debugViewer.ts +++ b/src/vs/workbench/parts/debug/browser/debugViewer.ts @@ -13,7 +13,7 @@ import errors = require('vs/base/common/errors'); import strings = require('vs/base/common/strings'); import { isMacintosh } from 'vs/base/common/platform'; import dom = require('vs/base/browser/dom'); -import mouse = require('vs/base/browser/mouseEvent'); +import {IMouseEvent} from 'vs/base/browser/mouseEvent'; import labels = require('vs/base/common/labels'); import actions = require('vs/base/common/actions'); import actionbar = require('vs/base/browser/ui/actionbar/actionbar'); @@ -195,10 +195,13 @@ export class BaseDebugController extends treedefaults.DefaultController { export class CallStackController extends BaseDebugController { - protected onLeftClick(tree: tree.ITree, element: any, event: mouse.IMouseEvent): boolean { + protected onLeftClick(tree: tree.ITree, element: any, event: IMouseEvent): boolean { if (typeof element === 'number') { return this.showMoreStackFrames(tree, element); } + if (element instanceof model.StackFrame) { + this.focusStackFrame(element, event, true); + } return super.onLeftClick(tree, element, event); } @@ -208,6 +211,9 @@ export class CallStackController extends BaseDebugController { if (typeof element === 'number') { return this.showMoreStackFrames(tree, element); } + if (element instanceof model.StackFrame) { + this.focusStackFrame(element, event, false); + } return super.onEnter(tree, event); } @@ -222,6 +228,13 @@ export class CallStackController extends BaseDebugController { return true; } + + private focusStackFrame(stackFrame: debug.IStackFrame, event: IKeyboardEvent|IMouseEvent, preserveFocus: boolean): void { + this.debugService.setFocusedStackFrameAndEvaluate(stackFrame).done(null, errors.onUnexpectedError); + + const sideBySide = (event && (event.ctrlKey || event.metaKey)); + this.debugService.openOrRevealSource(stackFrame.source, stackFrame.lineNumber, preserveFocus, sideBySide).done(null, errors.onUnexpectedError); + } } @@ -804,7 +817,7 @@ export class WatchExpressionsController extends BaseDebugController { } } - protected onLeftClick(tree: tree.ITree, element: any, event: mouse.IMouseEvent): boolean { + protected onLeftClick(tree: tree.ITree, element: any, event: IMouseEvent): boolean { // double click on primitive value: open input box to be able to select and copy value. if (element instanceof model.Expression && event.detail === 2) { const expression = element; @@ -1088,7 +1101,7 @@ export class BreakpointsAccessibilityProvider implements tree.IAccessibilityProv export class BreakpointsController extends BaseDebugController { - protected onLeftClick(tree: tree.ITree, element: any, event: mouse.IMouseEvent): boolean { + protected onLeftClick(tree: tree.ITree, element: any, event: IMouseEvent): boolean { if (element instanceof model.FunctionBreakpoint && event.detail === 2) { this.debugService.getViewModel().setSelectedFunctionBreakpoint(element); return true; diff --git a/src/vs/workbench/parts/debug/browser/debugViews.ts b/src/vs/workbench/parts/debug/browser/debugViews.ts index 30d85f69867..01859dc3490 100644 --- a/src/vs/workbench/parts/debug/browser/debugViews.ts +++ b/src/vs/workbench/parts/debug/browser/debugViews.ts @@ -227,32 +227,6 @@ export class CallStackView extends viewlet.CollapsibleViewletView { controller: new viewer.CallStackController(this.debugService, this.contextMenuService, actionProvider) }, debugTreeOptions(nls.localize({ comment: ['Debug is a noun in this context, not a verb.'], key: 'callStackAriaLabel'}, "Debug Call Stack"))); - this.toDispose.push(this.tree.addListener2('selection', (e: tree.ISelectionEvent) => { - if (!e.selection.length || !e.payload) { - // Ignore the event if it was not initated by user. - // Debug sometimes automaticaly sets the selected frame, and those events we need to ignore. - return; - } - const element = e.selection[0]; - - if (element instanceof StackFrame) { - const stackFrame = element; - this.debugService.setFocusedStackFrameAndEvaluate(stackFrame).done(null, errors.onUnexpectedError); - - const isMouse = (e.payload && e.payload.origin === 'mouse'); - let preserveFocus = isMouse; - - const originalEvent:KeyboardEvent|MouseEvent = e && e.payload && e.payload.originalEvent; - if (originalEvent && isMouse && originalEvent.detail === 2) { - preserveFocus = false; - originalEvent.preventDefault(); // focus moves to editor, we need to prevent default - } - - const sideBySide = (originalEvent && (originalEvent.ctrlKey || originalEvent.metaKey)); - this.debugService.openOrRevealSource(stackFrame.source, stackFrame.lineNumber, preserveFocus, sideBySide).done(null, errors.onUnexpectedError); - } - })); - this.toDispose.push(this.tree.addListener2(events.EventType.FOCUS, (e: tree.IFocusEvent) => { const isMouseClick = (e.payload && e.payload.origin === 'mouse'); const isStackFrameType = (e.focus instanceof StackFrame); From f2baddbf2f7e9013e3415772985bc468141a0ada Mon Sep 17 00:00:00 2001 From: isidor Date: Mon, 16 May 2016 15:05:12 +0200 Subject: [PATCH 192/297] debug: move more logic into breakpoints controller --- .../parts/debug/browser/debugViewer.ts | 24 ++++++++++++++++- .../parts/debug/browser/debugViews.ts | 27 +------------------ 2 files changed, 24 insertions(+), 27 deletions(-) diff --git a/src/vs/workbench/parts/debug/browser/debugViewer.ts b/src/vs/workbench/parts/debug/browser/debugViewer.ts index f6c5abf9726..cd2f0df3997 100644 --- a/src/vs/workbench/parts/debug/browser/debugViewer.ts +++ b/src/vs/workbench/parts/debug/browser/debugViewer.ts @@ -1106,10 +1106,26 @@ export class BreakpointsController extends BaseDebugController { this.debugService.getViewModel().setSelectedFunctionBreakpoint(element); return true; } + if (element instanceof model.Breakpoint) { + this.openBreakpointSource(element, event, true); + } return super.onLeftClick(tree, element, event); } + protected onEnter(tree: tree.ITree, event: IKeyboardEvent): boolean { + const element = tree.getFocus(); + if (element instanceof model.FunctionBreakpoint) { + this.debugService.getViewModel().setSelectedFunctionBreakpoint(element); + return true; + } + if (element instanceof model.Breakpoint) { + this.openBreakpointSource(element, event, false); + } + + return super.onEnter(tree, event); + } + protected onSpace(tree: tree.ITree, event: IKeyboardEvent): boolean { super.onSpace(tree, event); const element = tree.getFocus(); @@ -1118,7 +1134,6 @@ export class BreakpointsController extends BaseDebugController { return true; } - protected onDelete(tree: tree.ITree, event: IKeyboardEvent): boolean { const element = tree.getFocus(); if (element instanceof model.Breakpoint) { @@ -1133,4 +1148,11 @@ export class BreakpointsController extends BaseDebugController { return false; } + + private openBreakpointSource(breakpoint: debug.IBreakpoint, event: IKeyboardEvent|IMouseEvent, preserveFocus: boolean): void { + if (!breakpoint.source.inMemory) { + const sideBySide = (event && (event.ctrlKey || event.metaKey)); + this.debugService.openOrRevealSource(breakpoint.source, breakpoint.lineNumber, preserveFocus, sideBySide).done(null, errors.onUnexpectedError); + } + } } diff --git a/src/vs/workbench/parts/debug/browser/debugViews.ts b/src/vs/workbench/parts/debug/browser/debugViews.ts index 01859dc3490..09fae0331e1 100644 --- a/src/vs/workbench/parts/debug/browser/debugViews.ts +++ b/src/vs/workbench/parts/debug/browser/debugViews.ts @@ -16,7 +16,7 @@ import treeimpl = require('vs/base/parts/tree/browser/treeImpl'); import splitview = require('vs/base/browser/ui/splitview/splitview'); import viewlet = require('vs/workbench/browser/viewlet'); import debug = require('vs/workbench/parts/debug/common/debug'); -import { StackFrame, Expression, Variable, ExceptionBreakpoint, FunctionBreakpoint, Breakpoint } from 'vs/workbench/parts/debug/common/debugModel'; +import { StackFrame, Expression, Variable, ExceptionBreakpoint, FunctionBreakpoint } from 'vs/workbench/parts/debug/common/debugModel'; import viewer = require('vs/workbench/parts/debug/browser/debugViewer'); import debugactions = require('vs/workbench/parts/debug/electron-browser/debugActions'); import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; @@ -347,31 +347,6 @@ export class BreakpointsView extends viewlet.AdaptiveCollapsibleViewletView { this.tree.setInput(debugModel); - this.toDispose.push(this.tree.addListener2('selection', (e: tree.ISelectionEvent) => { - if (!e.selection.length) { - return; - } - const element = e.selection[0]; - if (!(element instanceof Breakpoint)) { - return; - } - - const breakpoint = element; - if (!breakpoint.source.inMemory) { - const isMouse = (e.payload.origin === 'mouse'); - let preserveFocus = isMouse; - - const originalEvent:KeyboardEvent|MouseEvent = e && e.payload && e.payload.originalEvent; - if (originalEvent && isMouse && originalEvent.detail === 2) { - preserveFocus = false; - originalEvent.preventDefault(); // focus moves to editor, we need to prevent default - } - - const sideBySide = (originalEvent && (originalEvent.ctrlKey || originalEvent.metaKey)); - this.debugService.openOrRevealSource(breakpoint.source, breakpoint.lineNumber, preserveFocus, sideBySide).done(null, errors.onUnexpectedError); - } - })); - this.toDispose.push(this.debugService.getViewModel().onDidSelectFunctionBreakpoint(fbp => { if (!fbp || !(fbp instanceof FunctionBreakpoint)) { return; From 97f7bdd677804456e28bb1dd51d69bf724aafa41 Mon Sep 17 00:00:00 2001 From: isidor Date: Mon, 16 May 2016 16:01:35 +0200 Subject: [PATCH 193/297] debug: allow to set focussed thread with no call stack fixes #6214 --- .../debug/browser/debugEditorModelManager.ts | 5 +++-- .../parts/debug/common/debugViewModel.ts | 6 ++++-- .../parts/debug/electron-browser/debugService.ts | 15 ++++++++++----- .../debug/test/common/debugViewModel.test.ts | 4 ++-- 4 files changed, 19 insertions(+), 11 deletions(-) diff --git a/src/vs/workbench/parts/debug/browser/debugEditorModelManager.ts b/src/vs/workbench/parts/debug/browser/debugEditorModelManager.ts index 9b163317f94..93407a49c27 100644 --- a/src/vs/workbench/parts/debug/browser/debugEditorModelManager.ts +++ b/src/vs/workbench/parts/debug/browser/debugEditorModelManager.ts @@ -134,13 +134,14 @@ export class DebugEditorModelManager implements IWorkbenchContribution { private createCallStackDecorations(modelUrlStr: string): editorcommon.IModelDeltaDecoration[] { const result: editorcommon.IModelDeltaDecoration[] = []; const focusedStackFrame = this.debugService.getViewModel().getFocusedStackFrame(); + const focusedThreadId = this.debugService.getViewModel().getFocusedThreadId(); const allThreads = this.debugService.getModel().getThreads(); - if (!focusedStackFrame || !allThreads[focusedStackFrame.threadId] || !allThreads[focusedStackFrame.threadId].getCachedCallStack()) { + if (!focusedStackFrame || !allThreads[focusedThreadId] || !allThreads[focusedThreadId].getCachedCallStack()) { return result; } // only show decorations for the currently focussed thread. - const thread = allThreads[focusedStackFrame.threadId]; + const thread = allThreads[focusedThreadId]; thread.getCachedCallStack().filter(sf => sf.source.uri.toString() === modelUrlStr).forEach(sf => { const wholeLineRange = createRange(sf.lineNumber, sf.column, sf.lineNumber, Number.MAX_VALUE); diff --git a/src/vs/workbench/parts/debug/common/debugViewModel.ts b/src/vs/workbench/parts/debug/common/debugViewModel.ts index 2701081a441..5de4b50287f 100644 --- a/src/vs/workbench/parts/debug/common/debugViewModel.ts +++ b/src/vs/workbench/parts/debug/common/debugViewModel.ts @@ -9,6 +9,7 @@ import debug = require('vs/workbench/parts/debug/common/debug'); export class ViewModel implements debug.IViewModel { private focusedStackFrame: debug.IStackFrame; + private focusedThread: debug.IThread; private selectedExpression: debug.IExpression; private selectedFunctionBreakpoint: debug.IFunctionBreakpoint; private _onDidFocusStackFrame: Emitter; @@ -31,8 +32,9 @@ export class ViewModel implements debug.IViewModel { return this.focusedStackFrame; } - public setFocusedStackFrame(focusedStackFrame: debug.IStackFrame): void { + public setFocusedStackFrame(focusedStackFrame: debug.IStackFrame, focusedThread: debug.IThread): void { this.focusedStackFrame = focusedStackFrame; + this.focusedThread = focusedThread; this._onDidFocusStackFrame.fire(focusedStackFrame); } @@ -41,7 +43,7 @@ export class ViewModel implements debug.IViewModel { } public getFocusedThreadId(): number { - return this.focusedStackFrame ? this.focusedStackFrame.threadId : 0; + return this.focusedThread ? this.focusedThread.threadId : 0; } public getSelectedExpression(): debug.IExpression { diff --git a/src/vs/workbench/parts/debug/electron-browser/debugService.ts b/src/vs/workbench/parts/debug/electron-browser/debugService.ts index 30c5fc809eb..0886a3850c3 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugService.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugService.ts @@ -251,17 +251,18 @@ export class DebugService implements debug.IDebugService { allThreadsStopped: event.body.allThreadsStopped }); - this.model.getThreads()[threadId].getCallStack(this).then(callStack => { + const thread = this.model.getThreads()[threadId]; + thread.getCallStack(this).then(callStack => { if (callStack.length > 0) { // focus first stack frame from top that has source location const stackFrameToFocus = arrays.first(callStack, sf => sf.source && sf.source.available, callStack[0]); - this.setFocusedStackFrameAndEvaluate(stackFrameToFocus).done(null, errors.onUnexpectedError); + this.setFocusedStackFrameAndEvaluate(stackFrameToFocus, thread).done(null, errors.onUnexpectedError); this.windowService.getWindow().focus(); aria.alert(nls.localize('debuggingPaused', "Debugging paused, reason {0}, {1} {2}", event.body.reason, stackFrameToFocus.source ? stackFrameToFocus.source.name : '', stackFrameToFocus.lineNumber)); return this.openOrRevealSource(stackFrameToFocus.source, stackFrameToFocus.lineNumber, false, false); } else { - this.setFocusedStackFrameAndEvaluate(null).done(null, errors.onUnexpectedError); + this.setFocusedStackFrameAndEvaluate(null, thread).done(null, errors.onUnexpectedError); } }); }, errors.onUnexpectedError); @@ -394,8 +395,12 @@ export class DebugService implements debug.IDebugService { return !!this.contextService.getWorkspace(); } - public setFocusedStackFrameAndEvaluate(focusedStackFrame: debug.IStackFrame): TPromise { - this.viewModel.setFocusedStackFrame(focusedStackFrame); + public setFocusedStackFrameAndEvaluate(focusedStackFrame: debug.IStackFrame, thread?: debug.IThread): TPromise { + if (!thread && focusedStackFrame) { + thread = this.model.getThreads()[focusedStackFrame.threadId]; + } + + this.viewModel.setFocusedStackFrame(focusedStackFrame, thread); if (focusedStackFrame) { return this.model.evaluateWatchExpressions(this.session, focusedStackFrame); } else { diff --git a/src/vs/workbench/parts/debug/test/common/debugViewModel.test.ts b/src/vs/workbench/parts/debug/test/common/debugViewModel.test.ts index a60ac72fd44..9f961b9db3e 100644 --- a/src/vs/workbench/parts/debug/test/common/debugViewModel.test.ts +++ b/src/vs/workbench/parts/debug/test/common/debugViewModel.test.ts @@ -5,7 +5,7 @@ import assert = require('assert'); import { ViewModel } from 'vs/workbench/parts/debug/common/debugViewModel'; -import { StackFrame, Expression } from 'vs/workbench/parts/debug/common/debugModel'; +import { StackFrame, Expression, Thread } from 'vs/workbench/parts/debug/common/debugModel'; suite('Debug - View Model', () => { var model: ViewModel; @@ -22,7 +22,7 @@ suite('Debug - View Model', () => { assert.equal(model.getFocusedStackFrame(), null); assert.equal(model.getFocusedThreadId(), 0); const frame = new StackFrame(1, 1, null, 'app.js', 1, 1); - model.setFocusedStackFrame(frame); + model.setFocusedStackFrame(frame, new Thread('myThread', 1)); assert.equal(model.getFocusedStackFrame(), frame); assert.equal(model.getFocusedThreadId(), 1); From df0e5235c5ed00421a247b650a4b08402ef527ef Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 16 May 2016 13:23:37 +0200 Subject: [PATCH 194/297] clean up some todos --- src/vs/code/electron-main/menus.ts | 4 ---- src/vs/code/electron-main/windows.ts | 4 ---- src/vs/workbench/electron-browser/media/shell.css | 2 +- 3 files changed, 1 insertion(+), 9 deletions(-) diff --git a/src/vs/code/electron-main/menus.ts b/src/vs/code/electron-main/menus.ts index 74cb9d3e79a..c5c16a0650a 100644 --- a/src/vs/code/electron-main/menus.ts +++ b/src/vs/code/electron-main/menus.ts @@ -409,10 +409,6 @@ export class VSCodeMenu { // Files let files = recentList.files; - if (platform.isMacintosh && recentList.files.length > 0) { - files = recentList.files.filter(f => recentList.folders.indexOf(f) < 0); // TODO@Ben migration (remove in the future) - } - if (files.length > 0) { openRecentMenu.append(__separator__()); diff --git a/src/vs/code/electron-main/windows.ts b/src/vs/code/electron-main/windows.ts index 8bf3c942a9c..f55f87d46e4 100644 --- a/src/vs/code/electron-main/windows.ts +++ b/src/vs/code/electron-main/windows.ts @@ -789,10 +789,6 @@ export class WindowsManager implements IWindowsService { files = arrays.distinct(files); folders = arrays.distinct(folders); - if (platform.isMacintosh && files.length > 0) { - files = files.filter(f => folders.indexOf(f) < 0); // TODO@Ben migration (remove in the future) - } - // Make sure it is bounded files = files.slice(0, 10); folders = folders.slice(0, 10); diff --git a/src/vs/workbench/electron-browser/media/shell.css b/src/vs/workbench/electron-browser/media/shell.css index 524dbf1887d..cdd8eabf705 100644 --- a/src/vs/workbench/electron-browser/media/shell.css +++ b/src/vs/workbench/electron-browser/media/shell.css @@ -171,7 +171,7 @@ .monaco-shell .part.editor .iframe-container, .monaco-shell .part.editor .binary-container { - outline: 0 !important; /* TODO@Ben we need focus indication for those too */ + outline: 0 !important; } /* END Keyboard Focus Indication Styles */ From e1f9857424c779de250824a9a5a446898941adb6 Mon Sep 17 00:00:00 2001 From: isidor Date: Mon, 16 May 2016 16:47:35 +0200 Subject: [PATCH 195/297] debug: smarter lazy transition to running state fixes #5966 fixes #5812 --- .../debug/electron-browser/debugService.ts | 53 ++++++++++--------- 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/src/vs/workbench/parts/debug/electron-browser/debugService.ts b/src/vs/workbench/parts/debug/electron-browser/debugService.ts index 0886a3850c3..b57113a0bf3 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugService.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugService.ts @@ -9,6 +9,7 @@ import lifecycle = require('vs/base/common/lifecycle'); import mime = require('vs/base/common/mime'); import Event, { Emitter } from 'vs/base/common/event'; import uri from 'vs/base/common/uri'; +import { RunOnceScheduler } from 'vs/base/common/async'; import { Action } from 'vs/base/common/actions'; import arrays = require('vs/base/common/arrays'); import types = require('vs/base/common/types'); @@ -857,41 +858,41 @@ export class DebugService implements debug.IDebugService { return this.session.pause({ threadId }); } - private lazyTransitionToRunningState(threadId?: number): void { - let cancelTransitionToRunningState = false; + let setNewFocusedStackFrameScheduler: RunOnceScheduler; const toDispose = this.session.onDidStop(e => { if (e.body.threadId === threadId || e.body.allThreadsStopped || !threadId) { - cancelTransitionToRunningState = true; + setNewFocusedStackFrameScheduler.cancel(); } }); - // Do not immediatly transition to running state since that might cause unnecessery flickering - // of the tree in the debug viewlet. Only transition if no stopped event has arrived in 500ms. - setTimeout(() => { + // TODO@Isidor temporary workaround for #1703 + if (this.session && strings.equalsIgnoreCase(this.session.configuration.type, 'php')) { + this.model.clearThreads(false, threadId); + } else { + this.model.clearThreads(false); + } + + // Get a top stack frame of a stopped thread if there is any. + const threads = this.model.getThreads(); + const stoppedReference = Object.keys(threads).filter(ref => threads[ref].stopped).pop(); + const stoppedThread = stoppedReference ? threads[parseInt(stoppedReference)] : null; + const callStack = stoppedThread ? stoppedThread.getCachedCallStack() : null; + const stackFrameToFocus = callStack && callStack.length > 0 ? callStack[0] : null; + + if (!stoppedThread) { + this.setStateAndEmit(this.configurationManager.configuration.noDebug ? debug.State.RunningNoDebug : debug.State.Running); + } + + // Do not immediatly set a new focused stack frame since that might cause unnecessery flickering + // of the tree in the debug viewlet. Only set focused stack frame if no stopped event has arrived in 500ms. + setNewFocusedStackFrameScheduler = new RunOnceScheduler(() => { toDispose.dispose(); - if (!cancelTransitionToRunningState) { - aria.status(nls.localize('debuggingContinued', "Debugging continued.")); - // TODO@Isidor temporary workaround for #1703 - if (this.session && strings.equalsIgnoreCase(this.session.configuration.type, 'php')) { - this.model.clearThreads(false, threadId); - } else { - this.model.clearThreads(false); - } + aria.status(nls.localize('debuggingContinued', "Debugging continued.")); - // Get a top stack frame of a stopped thread if there is any. - const threads = this.model.getThreads(); - const stoppedReference = Object.keys(threads).filter(ref => threads[ref].stopped).pop(); - const stoppedThread = stoppedReference ? threads[parseInt(stoppedReference)] : null; - const callStack = stoppedThread ? stoppedThread.getCachedCallStack() : null; - const stackFrameToFocus = callStack && callStack.length > 0 ? callStack[0] : null; - - this.setFocusedStackFrameAndEvaluate(stackFrameToFocus).done(null, errors.onUnexpectedError); - if (!stoppedThread) { - this.setStateAndEmit(this.configurationManager.configuration.noDebug ? debug.State.RunningNoDebug : debug.State.Running); - } - } + this.setFocusedStackFrameAndEvaluate(stackFrameToFocus).done(null, errors.onUnexpectedError); }, 500); + setNewFocusedStackFrameScheduler.schedule(); } private getDebugStringEditorInput(source: Source, value: string, mtype: string): DebugStringEditorInput { From 1460f60c1860f6173a12dd2632d324aa608ea160 Mon Sep 17 00:00:00 2001 From: Andre Weinand Date: Mon, 16 May 2016 18:04:37 +0200 Subject: [PATCH 196/297] node-debug: limit the number of locals transmitted by the scopes request; addresses #5645 --- extensions/node-debug/node-debug.azure.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/node-debug/node-debug.azure.json b/extensions/node-debug/node-debug.azure.json index 63c268656a8..1738a5dbafc 100644 --- a/extensions/node-debug/node-debug.azure.json +++ b/extensions/node-debug/node-debug.azure.json @@ -1,6 +1,6 @@ { "account": "monacobuild", "container": "debuggers", - "zip": "48428c0/node-debug.zip", + "zip": "624d700/node-debug.zip", "output": "" } From 593122fe025b85da4e9defc3d48ceb6afcca1f44 Mon Sep 17 00:00:00 2001 From: isidor Date: Mon, 16 May 2016 19:06:28 +0200 Subject: [PATCH 197/297] fixes #6396 --- src/vs/workbench/parts/debug/browser/media/debugViewlet.css | 1 - 1 file changed, 1 deletion(-) diff --git a/src/vs/workbench/parts/debug/browser/media/debugViewlet.css b/src/vs/workbench/parts/debug/browser/media/debugViewlet.css index ce7e59d2a64..3d5a788f92e 100644 --- a/src/vs/workbench/parts/debug/browser/media/debugViewlet.css +++ b/src/vs/workbench/parts/debug/browser/media/debugViewlet.css @@ -196,7 +196,6 @@ /* Variables & Expression view */ .debug-viewlet .scope { - text-transform: capitalize; font-weight: bold; font-size: 11px; } From 4458bdf5c031534c5b91cf0bb49ce19e9c034708 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 17 May 2016 11:22:28 +0200 Subject: [PATCH 198/297] merge tuples of equal Uri, #6373 --- .../vscode-api-tests/src/languages.test.ts | 49 +++++++++++++++++++ .../workbench/api/node/extHostDiagnostics.ts | 13 ++++- 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/extensions/vscode-api-tests/src/languages.test.ts b/extensions/vscode-api-tests/src/languages.test.ts index dc2d933e4c1..fe6200c00a3 100644 --- a/extensions/vscode-api-tests/src/languages.test.ts +++ b/extensions/vscode-api-tests/src/languages.test.ts @@ -79,6 +79,55 @@ suite('languages namespace tests', () => { collection.dispose(); }); + test('diagnostics collection, set with dupliclated tuples', function () { + let collection = languages.createDiagnosticCollection('test'); + let uri = Uri.parse('sc:hightower'); + collection.set([ + [uri, [new Diagnostic(new Range(0, 0, 0, 1), 'message-1')]], + [Uri.parse('some:thing'), [new Diagnostic(new Range(0, 0, 1, 1), 'something')]], + [uri, [new Diagnostic(new Range(0, 0, 0, 1), 'message-2')]], + ]); + + let array = collection.get(uri); + assert.equal(array.length, 2); + let [first, second] = array; + assert.equal(first.message, 'message-1'); + assert.equal(second.message, 'message-2'); + + // clear + collection.delete(uri); + assert.ok(!collection.has(uri)); + + // bad tuple clears 1/2 + collection.set([ + [uri, [new Diagnostic(new Range(0, 0, 0, 1), 'message-1')]], + [Uri.parse('some:thing'), [new Diagnostic(new Range(0, 0, 1, 1), 'something')]], + [uri, undefined] + ]); + assert.ok(!collection.has(uri)); + + // clear + collection.delete(uri); + assert.ok(!collection.has(uri)); + + // bad tuple clears 2/2 + collection.set([ + [uri, [new Diagnostic(new Range(0, 0, 0, 1), 'message-1')]], + [Uri.parse('some:thing'), [new Diagnostic(new Range(0, 0, 1, 1), 'something')]], + [uri, undefined], + [uri, [new Diagnostic(new Range(0, 0, 0, 1), 'message-2')]], + [uri, [new Diagnostic(new Range(0, 0, 0, 1), 'message-3')]], + ]); + + array = collection.get(uri); + assert.equal(array.length, 2); + [first, second] = array; + assert.equal(first.message, 'message-2'); + assert.equal(second.message, 'message-3'); + + collection.dispose(); + }); + test('diagnostics & CodeActionProvider', function (done) { class D2 extends Diagnostic { diff --git a/src/vs/workbench/api/node/extHostDiagnostics.ts b/src/vs/workbench/api/node/extHostDiagnostics.ts index 278050aae9b..3c9ca692e22 100644 --- a/src/vs/workbench/api/node/extHostDiagnostics.ts +++ b/src/vs/workbench/api/node/extHostDiagnostics.ts @@ -72,8 +72,19 @@ export class DiagnosticCollection implements vscode.DiagnosticCollection { toSync = []; for (let entry of first) { let [uri, diagnostics] = entry; - this._data[uri.toString()] = diagnostics; toSync.push(uri); + if (!diagnostics) { + // [Uri, undefined] means clear this + delete this._data[uri.toString()]; + } else { + // set or merge diagnostics + let existing = this._data[uri.toString()]; + if (existing) { + existing.push(...diagnostics); + } else { + this._data[uri.toString()] = diagnostics; + } + } } } From a16a9a2f46221ca2d78c1e8f39fd0c74c8d763eb Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 17 May 2016 11:27:50 +0200 Subject: [PATCH 199/297] update jsdoc for DiagnosticCollection#set and tuples, #6373 --- src/vs/vscode.d.ts | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index b07f77b49c8..26c3df7bb6b 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -2486,6 +2486,18 @@ declare namespace vscode { */ set(uri: Uri, diagnostics: Diagnostic[]): void; + /** + * Replace all entries in this collection. + * + * Diagnostics of multiple tuples of the same uri will be merged, e.g + * `[[file1, [d1]], [file1, [d2]]]` is equivalent to `[[file1, [d1, d2]]]`. + * If a diagnostics item is `undefined` as in `[file1, undefined]` + * all previous but not subsequent diagnostics are removed. + * + * @param entries An array of tuples, like `[[file1, [d1, d2]], [file2, [d3, d4, d5]]]`, or `undefined`. + */ + set(entries: [Uri, Diagnostic[]][]): void; + /** * Remove all diagnostics from this collection that belong * to the provided `uri`. The same as `#set(uri, undefined)`. @@ -2494,13 +2506,6 @@ declare namespace vscode { */ delete(uri: Uri): void; - /** - * Replace all entries in this collection. - * - * @param entries An array of tuples, like `[[file1, [d1, d2]], [file2, [d3, d4, d5]]]`, or `undefined`. - */ - set(entries: [Uri, Diagnostic[]][]): void; - /** * Remove all diagnostics from this collection. The same * as calling `#set(undefined)`; From a3f3b7562b1058614e56851ca7b15a03ba0932bd Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 17 May 2016 11:59:29 +0200 Subject: [PATCH 200/297] Revert "quick open: do not handle Enter on key_down, otherwise it bubbles to editor on key_up" This reverts commit ce3fb81e221457b0f8b404ac04f90a0fcac38d58. --- .../quickopen/browser/quickOpenWidget.ts | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/src/vs/base/parts/quickopen/browser/quickOpenWidget.ts b/src/vs/base/parts/quickopen/browser/quickOpenWidget.ts index 4527892af4e..97500cc6efb 100644 --- a/src/vs/base/parts/quickopen/browser/quickOpenWidget.ts +++ b/src/vs/base/parts/quickopen/browser/quickOpenWidget.ts @@ -111,7 +111,7 @@ export class QuickOpenWidget implements IModelProvider { this.builder = $().div((div: Builder) => { // Eventing - div.on(DOM.EventType.KEY_UP, (e: KeyboardEvent) => { + div.on(DOM.EventType.KEY_DOWN, (e: KeyboardEvent) => { let keyboardEvent: StandardKeyboardEvent = new StandardKeyboardEvent(e); if (keyboardEvent.keyCode === KeyCode.Escape) { DOM.EventHelper.stop(e, true); @@ -141,7 +141,6 @@ export class QuickOpenWidget implements IModelProvider { this.inputElement.setAttribute('aria-haspopup', 'false'); this.inputElement.setAttribute('aria-autocomplete', 'list'); - // Listen to some keys on key-down for faster type feedback DOM.addDisposableListener(this.inputBox.inputElement, DOM.EventType.KEY_DOWN, (e: KeyboardEvent) => { let keyboardEvent: StandardKeyboardEvent = new StandardKeyboardEvent(e); @@ -157,17 +156,8 @@ export class QuickOpenWidget implements IModelProvider { this.navigateInTree(keyboardEvent.keyCode, keyboardEvent.shiftKey); } - // Bug in IE 9: onInput is not fired for Backspace or Delete keys - else if (browser.isIE9 && (keyboardEvent.keyCode === KeyCode.Backspace || keyboardEvent.keyCode === KeyCode.Delete)) { - this.onType(); - } - }); - - DOM.addDisposableListener(this.inputBox.inputElement, DOM.EventType.KEY_UP, (e: KeyboardEvent) => { - let keyboardEvent: StandardKeyboardEvent = new StandardKeyboardEvent(e); - // Select element on Enter - if (keyboardEvent.keyCode === KeyCode.Enter) { + else if (keyboardEvent.keyCode === KeyCode.Enter) { DOM.EventHelper.stop(e, true); let focus = this.tree.getFocus(); @@ -175,6 +165,11 @@ export class QuickOpenWidget implements IModelProvider { this.elementSelected(focus, e); } } + + // Bug in IE 9: onInput is not fired for Backspace or Delete keys + else if (browser.isIE9 && (keyboardEvent.keyCode === KeyCode.Backspace || keyboardEvent.keyCode === KeyCode.Delete)) { + this.onType(); + } }); DOM.addDisposableListener(this.inputBox.inputElement, DOM.EventType.INPUT, (e: Event) => { From 11d1eb090e8bc9a5114ebac485876b4a6919b52e Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 17 May 2016 12:09:16 +0200 Subject: [PATCH 201/297] Insiders Build: Add message to switch over to the alpha build (fixes #6416) --- .../electron-browser/update.contribution.ts | 34 +++++++++++++++---- 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/parts/update/electron-browser/update.contribution.ts b/src/vs/workbench/parts/update/electron-browser/update.contribution.ts index 85ccc1594f8..fdc144e7952 100644 --- a/src/vs/workbench/parts/update/electron-browser/update.contribution.ts +++ b/src/vs/workbench/parts/update/electron-browser/update.contribution.ts @@ -12,12 +12,14 @@ import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { IPartService } from 'vs/workbench/services/part/common/partService'; import { IMessageService } from 'vs/platform/message/common/message'; import Severity from 'vs/base/common/severity'; import { ShowReleaseNotesAction } from 'vs/workbench/electron-browser/update'; import { Action } from 'vs/base/common/actions'; import { shell } from 'electron'; import * as semver from 'semver'; +import product from 'vs/platform/product'; const CloseAction = new Action('close', nls.localize('close', "Close"), '', true, () => null); @@ -29,6 +31,14 @@ const ShowLicenseAction = (licenseUrl: string) => new Action( () => { shell.openExternal(licenseUrl); return TPromise.as(null); } ); +const ReadAnnouncementAction = (url: string) => new Action( + 'read.announcement', + nls.localize('announcement', "Read Announcement"), + null, + true, + () => { shell.openExternal(url); return TPromise.as(null); } +); + export class UpdateContribution implements IWorkbenchContribution { private static KEY = 'releaseNotes/lastVersion'; @@ -37,14 +47,15 @@ export class UpdateContribution implements IWorkbenchContribution { constructor( @IStorageService storageService: IStorageService, @IWorkspaceContextService contextService: IWorkspaceContextService, - @IMessageService messageService: IMessageService + @IMessageService messageService: IMessageService, + @IPartService private partService: IPartService ) { const env = contextService.getConfiguration().env; const lastVersion = storageService.get(UpdateContribution.KEY, StorageScope.GLOBAL, ''); // was there an update? if (env.releaseNotesUrl && lastVersion && env.version !== lastVersion) { - setTimeout(() => { + partService.joinCreation().then(() => { messageService.show(Severity.Info, { message: nls.localize('releaseNotes', "Welcome to {0} v{1}! Would you like to read the Release Notes?", env.appName, env.version), actions: [ @@ -52,13 +63,12 @@ export class UpdateContribution implements IWorkbenchContribution { ShowReleaseNotesAction(env.releaseNotesUrl, true) ] }); - - }, 0); + }); } // should we show the new license? if (env.licenseUrl && lastVersion && semver.satisfies(lastVersion, '<1.0.0') && semver.satisfies(env.version, '>=1.0.0')) { - setTimeout(() => { + partService.joinCreation().then(() => { messageService.show(Severity.Info, { message: nls.localize('licenseChanged', "Our license terms have changed, please go through them.", env.appName, env.version), actions: [ @@ -66,8 +76,20 @@ export class UpdateContribution implements IWorkbenchContribution { ShowLicenseAction(env.licenseUrl) ] }); + }); + } - }, 0); + // insider retirement (TODO@ben remove) + if (product.quality === 'insider') { + partService.joinCreation().then(() => { + messageService.show(Severity.Info, { + message: nls.localize('insiderMsg', "The insiders channel is retired, please switch over to the new 'Alpha' channel"), + actions: [ + CloseAction, + ReadAnnouncementAction('http://go.microsoft.com/fwlink/?LinkId=798816') + ] + }); + }); } storageService.store(UpdateContribution.KEY, env.version, StorageScope.GLOBAL); From d301b07e4762e615586d84da65dbba2b298e1f50 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 17 May 2016 15:07:09 +0200 Subject: [PATCH 202/297] move id generator to core --- src/vs/{editor/common/core => base/common}/idGenerator.ts | 0 src/vs/editor/common/model/textModelWithDecorations.ts | 2 +- src/vs/editor/common/model/textModelWithMarkers.ts | 2 +- src/vs/editor/common/model/textModelWithTrackedRanges.ts | 2 +- 4 files changed, 3 insertions(+), 3 deletions(-) rename src/vs/{editor/common/core => base/common}/idGenerator.ts (100%) diff --git a/src/vs/editor/common/core/idGenerator.ts b/src/vs/base/common/idGenerator.ts similarity index 100% rename from src/vs/editor/common/core/idGenerator.ts rename to src/vs/base/common/idGenerator.ts diff --git a/src/vs/editor/common/model/textModelWithDecorations.ts b/src/vs/editor/common/model/textModelWithDecorations.ts index a2839b67fd6..339287ba7b9 100644 --- a/src/vs/editor/common/model/textModelWithDecorations.ts +++ b/src/vs/editor/common/model/textModelWithDecorations.ts @@ -8,7 +8,7 @@ import {onUnexpectedError} from 'vs/base/common/errors'; import {IHTMLContentElement, htmlContentElementArrEquals} from 'vs/base/common/htmlContent'; import * as strings from 'vs/base/common/strings'; import {TPromise} from 'vs/base/common/winjs.base'; -import {IdGenerator} from 'vs/editor/common/core/idGenerator'; +import {IdGenerator} from 'vs/base/common/idGenerator'; import {Range} from 'vs/editor/common/core/range'; import * as editorCommon from 'vs/editor/common/editorCommon'; import {TextModelWithTrackedRanges} from 'vs/editor/common/model/textModelWithTrackedRanges'; diff --git a/src/vs/editor/common/model/textModelWithMarkers.ts b/src/vs/editor/common/model/textModelWithMarkers.ts index 0e4aae8f7fb..7b4c3364b8f 100644 --- a/src/vs/editor/common/model/textModelWithMarkers.ts +++ b/src/vs/editor/common/model/textModelWithMarkers.ts @@ -5,7 +5,7 @@ 'use strict'; import {TPromise} from 'vs/base/common/winjs.base'; -import {IdGenerator} from 'vs/editor/common/core/idGenerator'; +import {IdGenerator} from 'vs/base/common/idGenerator'; import {Position} from 'vs/editor/common/core/position'; import {IEditorPosition, IModelContentChangedFlushEvent, IRawText, IReadOnlyLineMarker, ITextModelWithMarkers} from 'vs/editor/common/editorCommon'; import {ILineMarker, ModelLine} from 'vs/editor/common/model/modelLine'; diff --git a/src/vs/editor/common/model/textModelWithTrackedRanges.ts b/src/vs/editor/common/model/textModelWithTrackedRanges.ts index 06e5701cd42..08f8d10ed9b 100644 --- a/src/vs/editor/common/model/textModelWithTrackedRanges.ts +++ b/src/vs/editor/common/model/textModelWithTrackedRanges.ts @@ -5,7 +5,7 @@ 'use strict'; import {TPromise} from 'vs/base/common/winjs.base'; -import {IdGenerator} from 'vs/editor/common/core/idGenerator'; +import {IdGenerator} from 'vs/base/common/idGenerator'; import {Range} from 'vs/editor/common/core/range'; import * as editorCommon from 'vs/editor/common/editorCommon'; import {ILineMarker} from 'vs/editor/common/model/modelLine'; From 372dbdb7bd76382e69a29bf755ee071c0e1e539c Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 17 May 2016 15:11:43 +0200 Subject: [PATCH 203/297] use idGenerator --- src/vs/base/common/idGenerator.ts | 4 +++- src/vs/editor/common/model/textModelWithDecorations.ts | 4 ++-- src/vs/editor/common/model/textModelWithMarkers.ts | 4 ++-- src/vs/editor/common/model/textModelWithTrackedRanges.ts | 4 ++-- .../editor/contrib/referenceSearch/browser/referencesModel.ts | 4 ++-- 5 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/vs/base/common/idGenerator.ts b/src/vs/base/common/idGenerator.ts index 6a66c7da582..34ce058ff84 100644 --- a/src/vs/base/common/idGenerator.ts +++ b/src/vs/base/common/idGenerator.ts @@ -14,7 +14,9 @@ export class IdGenerator { this._lastId = 0; } - public generate(): string { + public nextId(): string { return this._prefix + (++this._lastId); } } + +export const defaultGenerator = new IdGenerator('id#'); \ No newline at end of file diff --git a/src/vs/editor/common/model/textModelWithDecorations.ts b/src/vs/editor/common/model/textModelWithDecorations.ts index 339287ba7b9..092eb35d318 100644 --- a/src/vs/editor/common/model/textModelWithDecorations.ts +++ b/src/vs/editor/common/model/textModelWithDecorations.ts @@ -415,7 +415,7 @@ export class TextModelWithDecorations extends TextModelWithTrackedRanges impleme private _addDecorationImpl(eventBuilder:DeferredEventsBuilder, ownerId:number, range:editorCommon.IEditorRange, options:ModelDecorationOptions): string { var rangeId = this.addTrackedRange(range, options.stickiness); - var decoration = new ModelInternalDecoration(this._decorationIdGenerator.generate(), ownerId, rangeId, options); + var decoration = new ModelInternalDecoration(this._decorationIdGenerator.nextId(), ownerId, rangeId, options); this.decorations[decoration.id] = decoration; this.rangeIdToDecorationId[rangeId] = decoration.id; @@ -432,7 +432,7 @@ export class TextModelWithDecorations extends TextModelWithTrackedRanges impleme for (let i = 0, len = newDecorations.length; i < len; i++) { let rangeId = rangeIds[i]; - var decoration = new ModelInternalDecoration(this._decorationIdGenerator.generate(), ownerId, rangeId, newDecorations[i].options); + var decoration = new ModelInternalDecoration(this._decorationIdGenerator.nextId(), ownerId, rangeId, newDecorations[i].options); this.decorations[decoration.id] = decoration; this.rangeIdToDecorationId[rangeId] = decoration.id; diff --git a/src/vs/editor/common/model/textModelWithMarkers.ts b/src/vs/editor/common/model/textModelWithMarkers.ts index 7b4c3364b8f..66b61109bc8 100644 --- a/src/vs/editor/common/model/textModelWithMarkers.ts +++ b/src/vs/editor/common/model/textModelWithMarkers.ts @@ -72,7 +72,7 @@ export class TextModelWithMarkers extends TextModelWithTokens implements ITextMo _addMarker(lineNumber:number, column:number, stickToPreviousCharacter:boolean): string { var pos = this.validatePosition(new Position(lineNumber, column)); - var marker = new LineMarker(this._markerIdGenerator.generate(), pos.column, stickToPreviousCharacter); + var marker = new LineMarker(this._markerIdGenerator.nextId(), pos.column, stickToPreviousCharacter); this._markerIdToMarker[marker.id] = marker; this._lines[pos.lineNumber - 1].addMarker(marker); @@ -89,7 +89,7 @@ export class TextModelWithMarkers extends TextModelWithTokens implements ITextMo for (let i = 0, len = newMarkers.length; i < len; i++) { let newMarker = newMarkers[i]; - let marker = new LineMarker(this._markerIdGenerator.generate(), newMarker.column, newMarker.stickToPreviousCharacter); + let marker = new LineMarker(this._markerIdGenerator.nextId(), newMarker.column, newMarker.stickToPreviousCharacter); this._markerIdToMarker[marker.id] = marker; if (!addMarkersPerLine[newMarker.lineNumber]) { diff --git a/src/vs/editor/common/model/textModelWithTrackedRanges.ts b/src/vs/editor/common/model/textModelWithTrackedRanges.ts index 08f8d10ed9b..21ccd3b9154 100644 --- a/src/vs/editor/common/model/textModelWithTrackedRanges.ts +++ b/src/vs/editor/common/model/textModelWithTrackedRanges.ts @@ -140,7 +140,7 @@ export class TextModelWithTrackedRanges extends TextModelWithMarkers implements var startMarkerId = this._addMarker(textRange.startLineNumber, textRange.startColumn, startMarkerSticksToPreviousCharacter); var endMarkerId = this._addMarker(textRange.endLineNumber, textRange.endColumn, endMarkerSticksToPreviousCharacter); - var range = new TrackedRange(this._rangeIdGenerator.generate(), startMarkerId, endMarkerId); + var range = new TrackedRange(this._rangeIdGenerator.nextId(), startMarkerId, endMarkerId); this._ranges[range.id] = range; this._markerIdToRangeId[startMarkerId] = range.id; this._markerIdToRangeId[endMarkerId] = range.id; @@ -176,7 +176,7 @@ export class TextModelWithTrackedRanges extends TextModelWithMarkers implements let startMarkerId = markerIds[2 * i]; let endMarkerId = markerIds[2 * i + 1]; - let range = new TrackedRange(this._rangeIdGenerator.generate(), startMarkerId, endMarkerId); + let range = new TrackedRange(this._rangeIdGenerator.nextId(), startMarkerId, endMarkerId); this._ranges[range.id] = range; this._markerIdToRangeId[startMarkerId] = range.id; this._markerIdToRangeId[endMarkerId] = range.id; diff --git a/src/vs/editor/contrib/referenceSearch/browser/referencesModel.ts b/src/vs/editor/contrib/referenceSearch/browser/referencesModel.ts index e281f462bd5..454dc15b12b 100644 --- a/src/vs/editor/contrib/referenceSearch/browser/referencesModel.ts +++ b/src/vs/editor/contrib/referenceSearch/browser/referencesModel.ts @@ -9,7 +9,7 @@ import Event, {fromEventEmitter} from 'vs/base/common/event'; import {basename, dirname} from 'vs/base/common/paths'; import * as strings from 'vs/base/common/strings'; import URI from 'vs/base/common/uri'; -import {generateUuid} from 'vs/base/common/uuid'; +import {defaultGenerator} from 'vs/base/common/idGenerator'; import {TPromise} from 'vs/base/common/winjs.base'; import {IEditorService} from 'vs/platform/editor/common/editor'; import {Range} from 'vs/editor/common/core/range'; @@ -25,7 +25,7 @@ export class OneReference { private _range: IRange, private _eventBus: EventEmitter ) { - this._id = generateUuid(); + this._id = defaultGenerator.nextId(); } public get id(): string { From 856fb636c75ce7014a7aa6ae29f5f9b975f41fa0 Mon Sep 17 00:00:00 2001 From: Andre Weinand Date: Tue, 17 May 2016 15:41:36 +0200 Subject: [PATCH 204/297] update node-debug --- extensions/node-debug/node-debug.azure.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/node-debug/node-debug.azure.json b/extensions/node-debug/node-debug.azure.json index 1738a5dbafc..ff103612c70 100644 --- a/extensions/node-debug/node-debug.azure.json +++ b/extensions/node-debug/node-debug.azure.json @@ -1,6 +1,6 @@ { "account": "monacobuild", "container": "debuggers", - "zip": "624d700/node-debug.zip", + "zip": "3c7ed19/node-debug.zip", "output": "" } From 6af3db5d8d76e2c59e33189bec1206d93d81fb95 Mon Sep 17 00:00:00 2001 From: isidor Date: Tue, 17 May 2016 15:58:33 +0200 Subject: [PATCH 205/297] fixes #6425 --- .../parts/debug/electron-browser/debug.contribution.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/parts/debug/electron-browser/debug.contribution.ts b/src/vs/workbench/parts/debug/electron-browser/debug.contribution.ts index e21596887d6..3d1481735ec 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debug.contribution.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debug.contribution.ts @@ -124,7 +124,7 @@ KeybindingsRegistry.registerCommandDesc({ .then(() => debugService.createSession(false)); } - return debugService.createSession(false, configuration); + return debugService.createSession(!!configuration.noDebug, configuration); }, when: KbExpr.not(debug.CONTEXT_IN_DEBUG_MODE), primary: undefined From 3354ae92f75fc86994ef7eb85fdd7537d078b21f Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Tue, 17 May 2016 15:59:59 +0200 Subject: [PATCH 206/297] fix #5918 --- .../src/features/jsonContributions.ts | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/extensions/javascript/src/features/jsonContributions.ts b/extensions/javascript/src/features/jsonContributions.ts index 1926b38fab7..e33ff6d1e91 100644 --- a/extensions/javascript/src/features/jsonContributions.ts +++ b/extensions/javascript/src/features/jsonContributions.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import {Location, getLocation, createScanner, SyntaxKind} from 'jsonc-parser'; +import {Location, getLocation, createScanner, SyntaxKind, ScanError} from 'jsonc-parser'; import {basename} from 'path'; import {BowerJSONContribution} from './bowerJSONContribution'; import {PackageJSONContribution} from './packageJSONContribution'; @@ -122,10 +122,7 @@ export class JSONCompletionItemProvider implements CompletionItemProvider { if (location.isAtPropertyKey) { let addValue = !location.previousNode || !location.previousNode.columnOffset; - let scanner = createScanner(document.getText(), true); - scanner.setPosition(offset); - scanner.scan(); - let isLast = scanner.getToken() === SyntaxKind.CloseBraceToken || scanner.getToken() === SyntaxKind.EOF; + let isLast = this.isLast(document, position); collectPromise = this.jsonContribution.collectPropertySuggestions(fileName, location, currentWord, addValue, isLast, collector); } else { if (location.path.length === 0) { @@ -153,4 +150,14 @@ export class JSONCompletionItemProvider implements CompletionItemProvider { } return text.substring(i+1, position.character); } + + private isLast(document: TextDocument, position: Position):boolean { + let scanner = createScanner(document.getText(), true); + scanner.setPosition(document.offsetAt(position)); + let nextToken = scanner.scan(); + if (nextToken === SyntaxKind.StringLiteral && scanner.getTokenError() === ScanError.UnexpectedEndOfString) { + nextToken= scanner.scan(); + } + return nextToken === SyntaxKind.CloseBraceToken || nextToken === SyntaxKind.EOF; + } } \ No newline at end of file From d8f6ac3501b6cfcc5db528ddc556dd3869355f82 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 17 May 2016 16:21:51 +0200 Subject: [PATCH 207/297] add new api command to compare two resources, fixes #1865 --- .../vscode-api-tests/src/commands.test.ts | 59 +++++++++++++------ .../workbench/api/node/extHostApiCommands.ts | 11 ++++ src/vs/workbench/electron-browser/actions.ts | 28 +++++++++ 3 files changed, 81 insertions(+), 17 deletions(-) diff --git a/extensions/vscode-api-tests/src/commands.test.ts b/extensions/vscode-api-tests/src/commands.test.ts index 5ffd6fd2ac7..495de2d1d96 100644 --- a/extensions/vscode-api-tests/src/commands.test.ts +++ b/extensions/vscode-api-tests/src/commands.test.ts @@ -40,23 +40,6 @@ suite('commands namespace tests', () => { }, done); }); - test('api-command: workbench.html.preview', function () { - - let registration = workspace.registerTextDocumentContentProvider('speciale', { - provideTextDocumentContent(uri) { - return `content of URI ${uri.toString()}`; - } - }); - - let virtualDocumentUri = Uri.parse('speciale://authority/path'); - - return commands.executeCommand('vscode.previewHtml', virtualDocumentUri).then(success => { - assert.ok(success); - registration.dispose(); - }); - - }); - test('editorCommand with extra args', function () { let args: IArguments; @@ -77,4 +60,46 @@ suite('commands namespace tests', () => { }); }); + + test('api-command: vscode.previewHtm', function () { + + let registration = workspace.registerTextDocumentContentProvider('speciale', { + provideTextDocumentContent(uri) { + return `content of URI ${uri.toString()}`; + } + }); + + let virtualDocumentUri = Uri.parse('speciale://authority/path'); + + return commands.executeCommand('vscode.previewHtml', virtualDocumentUri).then(success => { + assert.ok(success); + registration.dispose(); + }); + + }); + + test('api-command: vscode.diff', function () { + + let registration = workspace.registerTextDocumentContentProvider('sc', { + provideTextDocumentContent(uri) { + return `content of URI ${uri.toString()}#${Math.random()}`; + } + }); + + + let a = commands.executeCommand('vscode.diff', Uri.parse('sc:a'), Uri.parse('sc:b'), 'DIFF').then(value => { + assert.ok(value === void 0); + registration.dispose(); + }); + + let b = commands.executeCommand('vscode.diff', Uri.parse('sc:a'), Uri.parse('sc:b')).then(value => { + assert.ok(value === void 0); + registration.dispose(); + }); + + let c = commands.executeCommand('vscode.diff').then(() => assert.ok(false), () => assert.ok(true)); + let d = commands.executeCommand('vscode.diff', 1, 2, 3).then(() => assert.ok(false), () => assert.ok(true)); + + return Promise.all([a, b, c]); + }); }); diff --git a/src/vs/workbench/api/node/extHostApiCommands.ts b/src/vs/workbench/api/node/extHostApiCommands.ts index 92c8a164e52..666c57b577e 100644 --- a/src/vs/workbench/api/node/extHostApiCommands.ts +++ b/src/vs/workbench/api/node/extHostApiCommands.ts @@ -197,6 +197,17 @@ class ExtHostApiCommands { { name: 'configuration', description: '(optional) Name of the debug configuration from \'launch.json\' to use. Or a configuration json object to use.' } ] }); + + this._register('vscode.diff', (left: URI, right: URI, label: string) => { + return this._commands.executeCommand('_workbench.diff', [left, right, label]); + }, { + description: 'Opens the provided resources in the diff editor to compare their contents.', + args: [ + { name: 'left', description: 'Left-hand side resource of the diff editor', constraint: URI }, + { name: 'right', description: 'Right-hand side resource of the diff editor', constraint: URI }, + { name: 'title', description: '(optional) Human readable title for the diff editor', constraint: v => v === void 0 || typeof v === 'string' } + ] + }); } // --- command impl diff --git a/src/vs/workbench/electron-browser/actions.ts b/src/vs/workbench/electron-browser/actions.ts index 217820b5640..635937fcf9f 100644 --- a/src/vs/workbench/electron-browser/actions.ts +++ b/src/vs/workbench/electron-browser/actions.ts @@ -5,12 +5,15 @@ 'use strict'; +import URI from 'vs/base/common/uri'; import {TPromise} from 'vs/base/common/winjs.base'; import timer = require('vs/base/common/timer'); import paths = require('vs/base/common/paths'); import {Action} from 'vs/base/common/actions'; import {IWindowService} from 'vs/workbench/services/window/electron-browser/windowService'; import {IWorkbenchEditorService} from 'vs/workbench/services/editor/common/editorService'; +import {EditorInput} from 'vs/workbench/common/editor'; +import {DiffEditorInput} from 'vs/workbench/common/editor/diffEditorInput'; import nls = require('vs/nls'); import {IMessageService, Severity} from 'vs/platform/message/common/message'; import {IWindowConfiguration} from 'vs/workbench/electron-browser/window'; @@ -459,4 +462,29 @@ KeybindingsRegistry.registerCommandDesc({ }, when: undefined, primary: undefined +}); + +KeybindingsRegistry.registerCommandDesc({ + id: '_workbench.diff', + weight: KeybindingsRegistry.WEIGHT.workbenchContrib(0), + handler(accessor: ServicesAccessor, args: [URI, URI, string]) { + + const editorService = accessor.get(IWorkbenchEditorService); + let [left, right, label] = args; + + if (!label) { + label = nls.localize('diffLeftRightLabel', "{0} ⟷ {1}", left.toString(true), right.toString(true)); + } + + return TPromise.join([editorService.inputToType({ resource: left }), editorService.inputToType({ resource: right })]).then(inputs => { + const [left, right] = inputs; + + const diff = new DiffEditorInput(label, undefined, left, right); + return editorService.openEditor(diff); + }).then(() => { + return void 0; + }); + }, + when: undefined, + primary: undefined }); \ No newline at end of file From e78309f17eb2d36e56b75c9ca376606e84025025 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 17 May 2016 18:01:56 +0200 Subject: [PATCH 208/297] add a new config to enable word-based suggestions, fixes #5574 --- src/vs/editor/common/modes/abstractMode.ts | 6 +++-- .../common/modes/supports/suggestSupport.ts | 26 +++++++++++++++++-- src/vs/languages/php/common/php.ts | 4 ++- src/vs/languages/php/test/common/php.test.ts | 1 + 4 files changed, 32 insertions(+), 5 deletions(-) diff --git a/src/vs/editor/common/modes/abstractMode.ts b/src/vs/editor/common/modes/abstractMode.ts index 99c2892c2ec..7a0ca2d7ec1 100644 --- a/src/vs/editor/common/modes/abstractMode.ts +++ b/src/vs/editor/common/modes/abstractMode.ts @@ -9,6 +9,7 @@ import {IDisposable} from 'vs/base/common/lifecycle'; import {TPromise} from 'vs/base/common/winjs.base'; import {AsyncDescriptor1, createAsyncDescriptor1} from 'vs/platform/instantiation/common/descriptors'; import {IInstantiationService, optional} from 'vs/platform/instantiation/common/instantiation'; +import {IConfigurationService} from 'vs/platform/configuration/common/configuration'; import {IModeSupportChangedEvent} from 'vs/editor/common/editorCommon'; import * as modes from 'vs/editor/common/modes'; import {NullMode} from 'vs/editor/common/modes/nullMode'; @@ -251,13 +252,14 @@ export class FrankensteinMode extends AbstractMode { public suggestSupport:modes.ISuggestSupport; constructor( - descriptor:modes.IModeDescriptor, + descriptor: modes.IModeDescriptor, + @IConfigurationService configurationService: IConfigurationService, @optional(IEditorWorkerService) editorWorkerService: IEditorWorkerService ) { super(descriptor.id); if (editorWorkerService) { - this.suggestSupport = new TextualSuggestSupport(this.getId(), editorWorkerService); + this.suggestSupport = new TextualSuggestSupport(this.getId(), editorWorkerService, configurationService); } } } diff --git a/src/vs/editor/common/modes/supports/suggestSupport.ts b/src/vs/editor/common/modes/supports/suggestSupport.ts index d9b63f54f23..2e0bc9cfe9a 100644 --- a/src/vs/editor/common/modes/supports/suggestSupport.ts +++ b/src/vs/editor/common/modes/supports/suggestSupport.ts @@ -12,6 +12,10 @@ import {IFilter, matchesStrictPrefix, fuzzyContiguousFilter} from 'vs/base/commo import {handleEvent, isLineToken} from 'vs/editor/common/modes/supports'; import {IEditorWorkerService} from 'vs/editor/common/services/editorWorkerService'; import {IModelService} from 'vs/editor/common/services/modelService'; +import {IConfigurationService} from 'vs/platform/configuration/common/configuration'; +import {IConfigurationRegistry, Extensions} from 'vs/platform/configuration/common/configurationRegistry'; +import {Registry} from 'vs/platform/platform'; +import {localize} from 'vs/nls'; export interface ISuggestContribution { triggerCharacters: string[]; @@ -67,16 +71,34 @@ export class SuggestSupport implements ISuggestSupport { export class TextualSuggestSupport implements ISuggestSupport { + /* tslint:disable */ + private static _c = Registry.as(Extensions.Configuration).registerConfiguration({ + type: 'object', + properties: { + 'editor.wordBasedSuggestions': { + 'type': 'boolean', + 'description': localize('editor.wordBasedSuggestions', "Enable word based suggestions."), + 'default': true + } + } + }); + /* tslint:enable */ + private _modeId: string; private _editorWorkerService: IEditorWorkerService; + private _configurationService: IConfigurationService; - constructor(modeId: string, editorWorkerService: IEditorWorkerService) { + constructor(modeId: string, editorWorkerService: IEditorWorkerService, configurationService: IConfigurationService) { this._modeId = modeId; this._editorWorkerService = editorWorkerService; + this._configurationService = configurationService; } public suggest(resource: URI, position: IPosition, triggerCharacter?: string): TPromise { - return this._editorWorkerService.textualSuggest(resource, position); + let config = this._configurationService.getConfiguration<{ wordBasedSuggestions: boolean }>('editor'); + return (!config || config.wordBasedSuggestions) + ? this._editorWorkerService.textualSuggest(resource, position) + : TPromise.as([]); } public get filter(): IFilter { diff --git a/src/vs/languages/php/common/php.ts b/src/vs/languages/php/common/php.ts index 0221efe5b09..7f0e87d1bbe 100644 --- a/src/vs/languages/php/common/php.ts +++ b/src/vs/languages/php/common/php.ts @@ -14,6 +14,7 @@ import {RichEditSupport} from 'vs/editor/common/modes/supports/richEditSupport'; import {TokenizationSupport, ILeavingNestedModeData, ITokenizationCustomization} from 'vs/editor/common/modes/supports/tokenizationSupport'; import {TextualSuggestSupport} from 'vs/editor/common/modes/supports/suggestSupport'; import {IEditorWorkerService} from 'vs/editor/common/services/editorWorkerService'; +import {IConfigurationService} from 'vs/platform/configuration/common/configuration'; var brackets = (function() { @@ -460,6 +461,7 @@ export class PHPMode extends AbstractMode implements ITokenizationCustomization constructor( descriptor:Modes.IModeDescriptor, @IModeService modeService: IModeService, + @IConfigurationService configurationService: IConfigurationService, @IEditorWorkerService editorWorkerService: IEditorWorkerService ) { super(descriptor.id); @@ -493,7 +495,7 @@ export class PHPMode extends AbstractMode implements ITokenizationCustomization }); if (editorWorkerService) { - this.suggestSupport = new TextualSuggestSupport(this.getId(), editorWorkerService); + this.suggestSupport = new TextualSuggestSupport(this.getId(), editorWorkerService, configurationService); } } diff --git a/src/vs/languages/php/test/common/php.test.ts b/src/vs/languages/php/test/common/php.test.ts index 865cfdea340..e81f2d5f135 100644 --- a/src/vs/languages/php/test/common/php.test.ts +++ b/src/vs/languages/php/test/common/php.test.ts @@ -69,6 +69,7 @@ suite('Syntax Highlighting - PHP', () => { let mode = new PHPMode( { id: 'php' }, modeService, + null, null ); From 71dcb8069d67ca5f8bd2c82007eecf27b6d48646 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Tue, 17 May 2016 18:22:15 +0200 Subject: [PATCH 209/297] Adopt latest loader that adds `nodeModules` option to disambiguate node modules from AMD modules at bundle time and adopt it in the gulp tasks --- build/gulpfile.common.js | 4 ++-- src/vs/css.js | 14 ++++++-------- src/vs/loader.js | 38 ++++++++++++++++++++++---------------- src/vs/nls.js | 4 ++-- src/vs/text.js | 8 ++++---- 5 files changed, 36 insertions(+), 32 deletions(-) diff --git a/build/gulpfile.common.js b/build/gulpfile.common.js index 23b1480a418..47f24f687ef 100644 --- a/build/gulpfile.common.js +++ b/build/gulpfile.common.js @@ -40,10 +40,10 @@ exports.loaderConfig = function (emptyPaths) { paths: { 'vs/extensions': 'extensions' } - } + }, + nodeModules: emptyPaths||[] }; - (emptyPaths || []).forEach(function(m) { result.paths[m] = 'empty:'; }); return result; }; diff --git a/src/vs/css.js b/src/vs/css.js index 710116c0651..eaa5d6d8e47 100644 --- a/src/vs/css.js +++ b/src/vs/css.js @@ -13,8 +13,6 @@ *--------------------------------------------------------------------------------------------- *--------------------------------------------------------------------------------------------- *--------------------------------------------------------------------------------------------*/ -/// -/// 'use strict'; var __extends = (this && this.__extends) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; @@ -100,7 +98,7 @@ var CSSLoaderPlugin; this._insertLinkNode(linkNode); }; return BrowserCSSLoader; - })(); + }()); /** * Prior to IE10, IE could not go above 31 stylesheets in a page * http://blogs.msdn.com/b/ieinternals/archive/2011/05/14/internet-explorer-stylesheet-rule-selector-import-sheet-limit-maximum.aspx @@ -201,7 +199,7 @@ var CSSLoaderPlugin; } }; return IE9CSSLoader; - })(BrowserCSSLoader); + }(BrowserCSSLoader)); var IE8CSSLoader = (function (_super) { __extends(IE8CSSLoader, _super); function IE8CSSLoader() { @@ -214,7 +212,7 @@ var CSSLoaderPlugin; }; }; return IE8CSSLoader; - })(IE9CSSLoader); + }(IE9CSSLoader)); var NodeCSSLoader = (function () { function NodeCSSLoader() { this.fs = require.nodeRequire('fs'); @@ -229,7 +227,7 @@ var CSSLoaderPlugin; }; NodeCSSLoader.BOM_CHAR_CODE = 65279; return NodeCSSLoader; - })(); + }()); // ------------------------------ Finally, the plugin var CSSPlugin = (function () { function CSSPlugin(cssLoader) { @@ -279,7 +277,7 @@ var CSSLoaderPlugin; }; CSSPlugin.BUILD_MAP = {}; return CSSPlugin; - })(); + }()); CSSLoaderPlugin.CSSPlugin = CSSPlugin; var Utilities = (function () { function Utilities() { @@ -411,7 +409,7 @@ var CSSLoaderPlugin; }); }; return Utilities; - })(); + }()); CSSLoaderPlugin.Utilities = Utilities; (function () { var cssLoader = null; diff --git a/src/vs/loader.js b/src/vs/loader.js index b7d5f30c3a1..49317011d21 100644 --- a/src/vs/loader.js +++ b/src/vs/loader.js @@ -13,7 +13,6 @@ *--------------------------------------------------------------------------------------------- *--------------------------------------------------------------------------------------------- *--------------------------------------------------------------------------------------------*/ -/// 'use strict'; // Limitation: To load jquery through the loader, always require 'jquery' and add a path for it in the loader configuration var _amdLoaderGlobal = this, define; @@ -123,7 +122,7 @@ var AMDLoader; }; Utilities.NEXT_ANONYMOUS_ID = 1; return Utilities; - })(); + }()); AMDLoader.Utilities = Utilities; var ConfigurationOptionsUtil = (function () { function ConfigurationOptionsUtil() { @@ -189,6 +188,9 @@ var AMDLoader; options.baseUrl += '/'; } } + if (!Array.isArray(options.nodeModules)) { + options.nodeModules = []; + } return options; }; ConfigurationOptionsUtil.mergeConfigurationOptions = function (overwrite, base) { @@ -232,7 +234,7 @@ var AMDLoader; return ConfigurationOptionsUtil.validateConfigurationOptions(result); }; return ConfigurationOptionsUtil; - })(); + }()); AMDLoader.ConfigurationOptionsUtil = ConfigurationOptionsUtil; var Configuration = (function () { function Configuration(options) { @@ -428,6 +430,10 @@ var AMDLoader; * Transform a module id to a location. Appends .js to module ids */ Configuration.prototype.moduleIdToPaths = function (moduleId) { + if (this.isBuild() && this.options.nodeModules.indexOf(moduleId) >= 0) { + // This is a node module and we are at build time, drop it + return ['empty:']; + } var result = moduleId; if (this.overwriteModuleIdToPath.hasOwnProperty(result)) { result = this.overwriteModuleIdToPath[result]; @@ -522,7 +528,7 @@ var AMDLoader; this.options.onError(err); }; return Configuration; - })(); + }()); AMDLoader.Configuration = Configuration; // ------------------------------------------------------------------------ // ModuleIdResolver @@ -602,7 +608,7 @@ var AMDLoader; this._config.onError(err); }; return ModuleIdResolver; - })(); + }()); AMDLoader.ModuleIdResolver = ModuleIdResolver; // ------------------------------------------------------------------------ // Module @@ -832,7 +838,7 @@ var AMDLoader; return this._unresolvedDependenciesCount === 0; }; return Module; - })(); + }()); AMDLoader.Module = Module; // ------------------------------------------------------------------------ // LoaderEvent @@ -859,7 +865,7 @@ var AMDLoader; this.timestamp = timestamp; } return LoaderEvent; - })(); + }()); AMDLoader.LoaderEvent = LoaderEvent; var LoaderEventRecorder = (function () { function LoaderEventRecorder(loaderAvailableTimestamp) { @@ -872,7 +878,7 @@ var AMDLoader; return this._events; }; return LoaderEventRecorder; - })(); + }()); AMDLoader.LoaderEventRecorder = LoaderEventRecorder; var NullLoaderEventRecorder = (function () { function NullLoaderEventRecorder() { @@ -885,7 +891,7 @@ var AMDLoader; }; NullLoaderEventRecorder.INSTANCE = new NullLoaderEventRecorder(); return NullLoaderEventRecorder; - })(); + }()); AMDLoader.NullLoaderEventRecorder = NullLoaderEventRecorder; var ModuleManager = (function () { function ModuleManager(scriptLoader) { @@ -1520,7 +1526,7 @@ var AMDLoader; } }; return ModuleManager; - })(); + }()); AMDLoader.ModuleManager = ModuleManager; /** * Load `scriptSrc` only once (avoid multiple